diff options
Diffstat (limited to 'src/qml')
41 files changed, 864 insertions, 778 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index a34c1cbf0e..1960f1d65b 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1589,7 +1589,9 @@ enum MetaObjectResolverFlags { static void initMetaObjectResolver(QV4::IR::MemberExpressionResolver *resolver, QQmlPropertyCache *metaObject); -static QV4::IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, QV4::IR::MemberExpressionResolver *resolver, QV4::IR::Member *member) +static QV4::IR::DiscoveredType resolveQmlType(QQmlEnginePrivate *qmlEngine, + const QV4::IR::MemberExpressionResolver *resolver, + QV4::IR::Member *member) { QV4::IR::Type result = QV4::IR::VarType; @@ -1600,7 +1602,6 @@ static QV4::IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, QV4::IR::Membe int value = type->enumValue(qmlEngine, *member->name, &ok); if (ok) { member->setEnumValue(value); - resolver->clear(); return QV4::IR::SInt32Type; } } @@ -1611,25 +1612,30 @@ static QV4::IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, QV4::IR::Membe tdata->release(); // Decrease the reference count added from QQmlTypeLoader::getType() // When a singleton tries to reference itself, it may not be complete yet. if (tdata->isComplete()) { - initMetaObjectResolver(resolver, qmlEngine->propertyCacheForType(tdata->compiledData()->metaTypeId)); - resolver->flags |= AllPropertiesAreFinal; - return resolver->resolveMember(qmlEngine, resolver, member); + auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>(); + newResolver->owner = resolver->owner; + initMetaObjectResolver(newResolver, qmlEngine->propertyCacheForType(tdata->compiledData()->metaTypeId)); + newResolver->flags |= AllPropertiesAreFinal; + return newResolver->resolveMember(qmlEngine, newResolver, member); } } else if (type->isSingleton()) { const QMetaObject *singletonMeta = type->singletonInstanceInfo()->instanceMetaObject; if (singletonMeta) { // QJSValue-based singletons cannot be accelerated - initMetaObjectResolver(resolver, qmlEngine->cache(singletonMeta)); + auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>(); + newResolver->owner = resolver->owner; + initMetaObjectResolver(newResolver, qmlEngine->cache(singletonMeta)); member->kind = QV4::IR::Member::MemberOfSingletonObject; - return resolver->resolveMember(qmlEngine, resolver, member); + return newResolver->resolveMember(qmlEngine, newResolver, member); } } else if (const QMetaObject *attachedMeta = type->attachedPropertiesType(qmlEngine)) { QQmlPropertyCache *cache = qmlEngine->cache(attachedMeta); - initMetaObjectResolver(resolver, cache); + auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>(); + newResolver->owner = resolver->owner; + initMetaObjectResolver(newResolver, cache); member->setAttachedPropertiesId(type->attachedPropertiesId(qmlEngine)); - return resolver->resolveMember(qmlEngine, resolver, member); + return newResolver->resolveMember(qmlEngine, newResolver, member); } - resolver->clear(); return result; } @@ -1643,7 +1649,9 @@ static void initQmlTypeResolver(QV4::IR::MemberExpressionResolver *resolver, QQm resolver->flags = 0; } -static QV4::IR::Type resolveImportNamespace(QQmlEnginePrivate *, QV4::IR::MemberExpressionResolver *resolver, QV4::IR::Member *member) +static QV4::IR::DiscoveredType resolveImportNamespace( + QQmlEnginePrivate *, const QV4::IR::MemberExpressionResolver *resolver, + QV4::IR::Member *member) { QV4::IR::Type result = QV4::IR::VarType; QQmlTypeNameCache *typeNamespace = static_cast<QQmlTypeNameCache*>(resolver->extraData); @@ -1660,19 +1668,21 @@ static QV4::IR::Type resolveImportNamespace(QQmlEnginePrivate *, QV4::IR::Member // through the singleton getter in the run-time. Until then we // can't accelerate access :( if (!r.type->isSingleton()) { - initQmlTypeResolver(resolver, r.type); - return QV4::IR::QObjectType; + auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>(); + newResolver->owner = resolver->owner; + initQmlTypeResolver(newResolver, r.type); + return QV4::IR::DiscoveredType(newResolver); } } else { Q_ASSERT(false); // How can this happen? } } - resolver->clear(); return result; } -static void initImportNamespaceResolver(QV4::IR::MemberExpressionResolver *resolver, QQmlTypeNameCache *imports, const void *importNamespace) +static void initImportNamespaceResolver(QV4::IR::MemberExpressionResolver *resolver, + QQmlTypeNameCache *imports, const void *importNamespace) { resolver->resolveMember = &resolveImportNamespace; resolver->data = const_cast<void*>(importNamespace); @@ -1680,7 +1690,9 @@ static void initImportNamespaceResolver(QV4::IR::MemberExpressionResolver *resol resolver->flags = 0; } -static QV4::IR::Type resolveMetaObjectProperty(QQmlEnginePrivate *qmlEngine, QV4::IR::MemberExpressionResolver *resolver, QV4::IR::Member *member) +static QV4::IR::DiscoveredType resolveMetaObjectProperty( + QQmlEnginePrivate *qmlEngine, const QV4::IR::MemberExpressionResolver *resolver, + QV4::IR::Member *member) { QV4::IR::Type result = QV4::IR::VarType; QQmlPropertyCache *metaObject = static_cast<QQmlPropertyCache*>(resolver->data); @@ -1694,7 +1706,6 @@ static QV4::IR::Type resolveMetaObjectProperty(QQmlEnginePrivate *qmlEngine, QV4 int value = metaEnum.keyToValue(enumName.constData(), &ok); if (ok) { member->setEnumValue(value); - resolver->clear(); return QV4::IR::SInt32Type; } } @@ -1739,21 +1750,25 @@ static QV4::IR::Type resolveMetaObjectProperty(QQmlEnginePrivate *qmlEngine, QV4 default: if (property->isQObject()) { if (QQmlPropertyCache *cache = qmlEngine->propertyCacheForType(property->propType)) { - initMetaObjectResolver(resolver, cache); - return QV4::IR::QObjectType; + auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>(); + newResolver->owner = resolver->owner; + initMetaObjectResolver(newResolver, cache); + return QV4::IR::DiscoveredType(newResolver); } } 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; + auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>(); + newResolver->owner = resolver->owner; + initMetaObjectResolver(newResolver, cache); + newResolver->flags |= ResolveTypeInformationOnly; + return QV4::IR::DiscoveredType(newResolver); } } break; } } } - resolver->clear(); + return result; } @@ -1809,6 +1824,7 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int result = _block->TEMP(result->index); if (mapping.type) { result->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>(); + result->memberResolver->owner = _function; initMetaObjectResolver(result->memberResolver, mapping.type); result->memberResolver->flags |= AllPropertiesAreFinal; } @@ -1831,6 +1847,7 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int result = _block->TEMP(result->index); result->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>(); + result->memberResolver->owner = _function; initQmlTypeResolver(result->memberResolver, r.type); return result; } else { @@ -1839,6 +1856,7 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int namespaceName->freeOfSideEffects = true; QV4::IR::Temp *result = _block->TEMP(_block->newTemp()); result->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>(); + result->memberResolver->owner = _function; initImportNamespaceResolver(result->memberResolver, imports, r.importNamespace); _block->MOVE(result, namespaceName); @@ -1855,6 +1873,7 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int if (pd) { QV4::IR::Temp *base = _block->TEMP(_qmlContextTemp); base->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>(); + base->memberResolver->owner = _function; initMetaObjectResolver(base->memberResolver, _scopeObject); return _block->MEMBER(base, _function->newString(name), pd, QV4::IR::Member::MemberOfQmlScopeObject); } @@ -1868,6 +1887,7 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int if (pd) { QV4::IR::Temp *base = _block->TEMP(_qmlContextTemp); base->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>(); + base->memberResolver->owner = _function; initMetaObjectResolver(base->memberResolver, _contextObject); return _block->MEMBER(base, _function->newString(name), pd, QV4::IR::Member::MemberOfQmlContextObject); } diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 33716d57b8..a71793f2b6 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -2731,8 +2731,8 @@ bool QQmlJavaScriptBindingExpressionSimplificationPass::simplifyBinding(QV4::IR: if (function->basicBlockCount() > 10) return false; - foreach (QV4::IR::BasicBlock *bb, function->basicBlocks()) { - foreach (QV4::IR::Stmt *s, bb->statements()) { + for (QV4::IR::BasicBlock *bb : function->basicBlocks()) { + for (QV4::IR::Stmt *s : bb->statements()) { s->accept(this); if (!_canSimplify) return false; @@ -2901,8 +2901,8 @@ void QQmlIRFunctionCleanser::clean() module->functions = newFunctions; foreach (QV4::IR::Function *function, module->functions) { - foreach (QV4::IR::BasicBlock *block, function->basicBlocks()) { - foreach (QV4::IR::Stmt *s, block->statements()) { + for (QV4::IR::BasicBlock *block : function->basicBlocks()) { + for (QV4::IR::Stmt *s : block->statements()) { s->accept(this); } } diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp index b3468848ca..be10d50e9b 100644 --- a/src/qml/compiler/qv4isel_moth.cpp +++ b/src/qml/compiler/qv4isel_moth.cpp @@ -255,16 +255,16 @@ protected: if (IR::Jump *jump = s->asJump()) { IR::MoveMapping moves; - foreach (IR::Stmt *succStmt, jump->target->statements()) { + for (IR::Stmt *succStmt : jump->target->statements()) { if (IR::Phi *phi = succStmt->asPhi()) { forceActivation(*phi->targetTemp); - for (int i = 0, ei = phi->d->incoming.size(); i != ei; ++i) { - IR::Expr *e = phi->d->incoming[i]; + for (int i = 0, ei = phi->incoming.size(); i != ei; ++i) { + IR::Expr *e = phi->incoming[i]; if (IR::Temp *t = e->asTemp()) { forceActivation(*t); } if (jump->target->in[i] == _currentBasicBlock) - moves.add(phi->d->incoming[i], phi->targetTemp); + moves.add(phi->incoming[i], phi->targetTemp); } } else { break; @@ -303,7 +303,7 @@ protected: #if !defined(QT_NO_DEBUG) Q_ASSERT(_stackSlotForTemp.contains(phi->targetTemp->index)); Q_ASSERT(_slotIsInUse[_stackSlotForTemp[phi->targetTemp->index]]); - foreach (IR::Expr *e, phi->d->incoming) { + foreach (IR::Expr *e, phi->incoming) { if (IR::Temp *t = e->asTemp()) Q_ASSERT(_stackSlotForTemp.contains(t->index)); } @@ -385,7 +385,7 @@ void InstructionSelection::run(int functionIndex) addInstruction(push); currentLine = 0; - QVector<IR::BasicBlock *> basicBlocks = _function->basicBlocks(); + const QVector<IR::BasicBlock *> &basicBlocks = _function->basicBlocks(); for (int i = 0, ei = basicBlocks.size(); i != ei; ++i) { blockNeedsDebugInstruction = irModule->debugMode; _block = basicBlocks[i]; @@ -404,7 +404,7 @@ void InstructionSelection::run(int functionIndex) exceptionHandler = _block->catchBlock; } - foreach (IR::Stmt *s, _block->statements()) { + for (IR::Stmt *s : _block->statements()) { _currentStatement = s; if (s->location.isValid()) { diff --git a/src/qml/compiler/qv4isel_util_p.h b/src/qml/compiler/qv4isel_util_p.h index 9ef3ef6721..674fc01623 100644 --- a/src/qml/compiler/qv4isel_util_p.h +++ b/src/qml/compiler/qv4isel_util_p.h @@ -145,11 +145,11 @@ public: { _stackSlotForTemp.reserve(function->tempCount); - foreach (IR::BasicBlock *bb, function->basicBlocks()) { + for (IR::BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) continue; _currentBasicBlock = bb; - foreach (IR::Stmt *s, bb->statements()) + for (IR::Stmt *s : bb->statements()) process(s); } diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp index 4c87b7557e..b28db59190 100644 --- a/src/qml/compiler/qv4jsir.cpp +++ b/src/qml/compiler/qv4jsir.cpp @@ -511,344 +511,23 @@ void Function::setStatementCount(int cnt) _statementCount = cnt; } -BasicBlock::~BasicBlock() -{ - for (Stmt *s : qAsConst(_statements)) { - Phi *p = s->asPhi(); - if (p) - p->destroyData(); - } -} - -unsigned BasicBlock::newTemp() -{ - Q_ASSERT(!isRemoved()); - return function->tempCount++; -} - -Temp *BasicBlock::TEMP(unsigned index) -{ - Q_ASSERT(!isRemoved()); - Temp *e = function->New<Temp>(); - e->init(Temp::VirtualRegister, index); - return e; -} - -ArgLocal *BasicBlock::ARG(unsigned index, unsigned scope) -{ - Q_ASSERT(!isRemoved()); - ArgLocal *e = function->New<ArgLocal>(); - e->init(scope ? ArgLocal::ScopedFormal : ArgLocal::Formal, index, scope); - return e; -} - -ArgLocal *BasicBlock::LOCAL(unsigned index, unsigned scope) -{ - Q_ASSERT(!isRemoved()); - ArgLocal *e = function->New<ArgLocal>(); - e->init(scope ? ArgLocal::ScopedLocal : ArgLocal::Local, index, scope); - return e; -} - -Expr *BasicBlock::CONST(Type type, double value) -{ - Q_ASSERT(!isRemoved()); - Const *e = function->New<Const>(); - if (type == NumberType) { - int ival = (int)value; - // +0 != -0, so we need to convert to double when negating 0 - if (ival == value && !(value == 0 && isNegative(value))) - type = SInt32Type; - else - type = DoubleType; - } else if (type == NullType) { - value = 0; - } else if (type == UndefinedType) { - value = qQNaN(); - } - - e->init(type, value); - return e; -} - -Expr *BasicBlock::STRING(const QString *value) -{ - Q_ASSERT(!isRemoved()); - String *e = function->New<String>(); - e->init(value); - return e; -} - -Expr *BasicBlock::REGEXP(const QString *value, int flags) -{ - Q_ASSERT(!isRemoved()); - RegExp *e = function->New<RegExp>(); - e->init(value, flags); - return e; -} - -Name *BasicBlock::NAME(const QString &id, quint32 line, quint32 column) -{ - Q_ASSERT(!isRemoved()); - Name *e = function->New<Name>(); - e->init(function->newString(id), line, column); - return e; -} - -Name *BasicBlock::GLOBALNAME(const QString &id, quint32 line, quint32 column) -{ - Q_ASSERT(!isRemoved()); - Name *e = function->New<Name>(); - e->initGlobal(function->newString(id), line, column); - return e; -} - - -Name *BasicBlock::NAME(Name::Builtin builtin, quint32 line, quint32 column) -{ - Q_ASSERT(!isRemoved()); - Name *e = function->New<Name>(); - e->init(builtin, line, column); - return e; -} - -Closure *BasicBlock::CLOSURE(int functionInModule) -{ - Q_ASSERT(!isRemoved()); - Closure *clos = function->New<Closure>(); - clos->init(functionInModule, function->module->functions.at(functionInModule)->name); - return clos; -} - -Expr *BasicBlock::CONVERT(Expr *expr, Type type) -{ - Q_ASSERT(!isRemoved()); - Convert *e = function->New<Convert>(); - e->init(expr, type); - return e; -} - -Expr *BasicBlock::UNOP(AluOp op, Expr *expr) -{ - Q_ASSERT(!isRemoved()); - Unop *e = function->New<Unop>(); - e->init(op, expr); - return e; -} - -Expr *BasicBlock::BINOP(AluOp op, Expr *left, Expr *right) -{ - Q_ASSERT(!isRemoved()); - Binop *e = function->New<Binop>(); - e->init(op, left, right); - return e; -} - -Expr *BasicBlock::CALL(Expr *base, ExprList *args) -{ - Q_ASSERT(!isRemoved()); - Call *e = function->New<Call>(); - e->init(base, args); - int argc = 0; - for (ExprList *it = args; it; it = it->next) - ++argc; - function->maxNumberOfArguments = qMax(function->maxNumberOfArguments, argc); - return e; -} - -Expr *BasicBlock::NEW(Expr *base, ExprList *args) -{ - Q_ASSERT(!isRemoved()); - New *e = function->New<New>(); - e->init(base, args); - return e; -} - -Expr *BasicBlock::SUBSCRIPT(Expr *base, Expr *index) -{ - Q_ASSERT(!isRemoved()); - Subscript *e = function->New<Subscript>(); - e->init(base, index); - return e; -} - -Expr *BasicBlock::MEMBER(Expr *base, const QString *name, QQmlPropertyData *property, uchar kind, int attachedPropertiesIdOrEnumValue) -{ - Q_ASSERT(!isRemoved()); - Member*e = function->New<Member>(); - e->init(base, name, property, kind, attachedPropertiesIdOrEnumValue); - return e; -} - -Stmt *BasicBlock::EXP(Expr *expr) -{ - Q_ASSERT(!isRemoved()); - if (isTerminated()) - return 0; - - Exp *s = function->NewStmt<Exp>(); - s->init(expr); - appendStatement(s); - return s; -} - -Stmt *BasicBlock::MOVE(Expr *target, Expr *source) -{ - Q_ASSERT(!isRemoved()); - if (isTerminated()) - return 0; - - Move *s = function->NewStmt<Move>(); - s->init(target, source); - appendStatement(s); - return s; -} - -Stmt *BasicBlock::JUMP(BasicBlock *target) -{ - Q_ASSERT(!isRemoved()); - if (isTerminated()) - return 0; - - Jump *s = function->NewStmt<Jump>(); - s->init(target); - appendStatement(s); - - Q_ASSERT(! out.contains(target)); - out.append(target); - - Q_ASSERT(! target->in.contains(this)); - target->in.append(this); - - return s; -} - -Stmt *BasicBlock::CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse) -{ - Q_ASSERT(!isRemoved()); - if (isTerminated()) - return 0; - - if (iftrue == iffalse) { - MOVE(TEMP(newTemp()), cond); - return JUMP(iftrue); - } - - CJump *s = function->NewStmt<CJump>(); - s->init(cond, iftrue, iffalse, this); - appendStatement(s); - - Q_ASSERT(! out.contains(iftrue)); - out.append(iftrue); - - Q_ASSERT(! iftrue->in.contains(this)); - iftrue->in.append(this); - - Q_ASSERT(! out.contains(iffalse)); - out.append(iffalse); - - Q_ASSERT(! iffalse->in.contains(this)); - iffalse->in.append(this); - - return s; -} - -Stmt *BasicBlock::RET(Expr *expr) -{ - Q_ASSERT(!isRemoved()); - if (isTerminated()) - return 0; - - Ret *s = function->NewStmt<Ret>(); - s->init(expr); - appendStatement(s); - return s; -} - void BasicBlock::setStatements(const QVector<Stmt *> &newStatements) { Q_ASSERT(!isRemoved()); Q_ASSERT(newStatements.size() >= _statements.size()); - // FIXME: this gets quite inefficient for large basic-blocks, so this function/case should be re-worked. for (Stmt *s : qAsConst(_statements)) { - Phi *p = s->asPhi(); - if (!p) - continue; - - if (!newStatements.contains(p)) - p->destroyData(); + if (Phi *p = s->asPhi()) { + if (!newStatements.contains(p)) { + // phi-node was not copied over, so: + p->destroyData(); + } + } else { + break; + } } _statements = newStatements; } -void BasicBlock::appendStatement(Stmt *statement) -{ - Q_ASSERT(!isRemoved()); - if (nextLocation.startLine) - statement->location = nextLocation; - _statements.append(statement); -} - -void BasicBlock::prependStatement(Stmt *stmt) -{ - Q_ASSERT(!isRemoved()); - _statements.prepend(stmt); -} - -void BasicBlock::prependStatements(const QVector<Stmt *> &stmts) -{ - Q_ASSERT(!isRemoved()); - QVector<Stmt *> newStmts = stmts; - newStmts += _statements; - _statements = newStmts; -} - -void BasicBlock::insertStatementBefore(Stmt *before, Stmt *newStmt) -{ - int idx = _statements.indexOf(before); - Q_ASSERT(idx >= 0); - _statements.insert(idx, newStmt); -} - -void BasicBlock::insertStatementBefore(int index, Stmt *newStmt) -{ - Q_ASSERT(index >= 0); - _statements.insert(index, newStmt); -} - -void BasicBlock::insertStatementBeforeTerminator(Stmt *stmt) -{ - Q_ASSERT(!isRemoved()); - _statements.insert(_statements.size() - 1, stmt); -} - -void BasicBlock::replaceStatement(int index, Stmt *newStmt) -{ - Q_ASSERT(!isRemoved()); - Phi *p = _statements[index]->asPhi(); - if (p) - p->destroyData(); - _statements[index] = newStmt; -} - -void BasicBlock::removeStatement(Stmt *stmt) -{ - Q_ASSERT(!isRemoved()); - Phi *p = stmt->asPhi(); - if (p) - p->destroyData(); - _statements.remove(_statements.indexOf(stmt)); -} - -void BasicBlock::removeStatement(int idx) -{ - Q_ASSERT(!isRemoved()); - Phi *p = _statements[idx]->asPhi(); - if (p) - p->destroyData(); - _statements.remove(idx); -} - CloneExpr::CloneExpr(BasicBlock *block) : block(block), cloned(0) { @@ -1084,13 +763,13 @@ void IRPrinter::visitPhi(Phi *s) s->targetTemp->accept(this); *out << " = phi "; - for (int i = 0, ei = s->d->incoming.size(); i < ei; ++i) { + for (int i = 0, ei = s->incoming.size(); i < ei; ++i) { if (i > 0) *out << ", "; if (currentBB) *out << 'L' << currentBB->in.at(i)->index() << ": "; - if (s->d->incoming[i]) - s->d->incoming[i]->accept(this); + if (s->incoming[i]) + s->incoming[i]->accept(this); } } diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h index 974e8dfe0d..eafecae494 100644 --- a/src/qml/compiler/qv4jsir_p.h +++ b/src/qml/compiler/qv4jsir_p.h @@ -244,13 +244,37 @@ struct StmtVisitor { virtual void visitPhi(Phi *) = 0; }; +struct MemberExpressionResolver; + +struct DiscoveredType { + int type; + MemberExpressionResolver *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); } + + bool operator!=(Type other) const { return type != other; } + bool operator==(Type other) const { return type == other; } + bool operator==(const DiscoveredType &other) const { return type == other.type; } + bool operator!=(const DiscoveredType &other) const { return type != other.type; } +}; struct MemberExpressionResolver { - typedef Type (*ResolveFunction)(QQmlEnginePrivate *engine, MemberExpressionResolver *resolver, Member *member); + typedef DiscoveredType (*ResolveFunction)(QQmlEnginePrivate *engine, + const MemberExpressionResolver *resolver, + Member *member); MemberExpressionResolver() - : resolveMember(0), data(0), extraData(0), flags(0) {} + : resolveMember(0), data(0), extraData(0), owner(nullptr), flags(0) {} bool isValid() const { return !!resolveMember; } void clear() { *this = MemberExpressionResolver(); } @@ -258,6 +282,7 @@ struct MemberExpressionResolver ResolveFunction resolveMember; void *data; // Could be pointer to meta object, importNameSpace, etc. - depends on resolveMember implementation void *extraData; // Could be QQmlTypeNameCache + Function *owner; unsigned int flags; }; @@ -751,23 +776,21 @@ struct Ret: Stmt { virtual Ret *asRet() { return this; } }; +// Phi nodes can only occur at the start of a basic block. If there are any, they need to be +// subsequent to eachother, and the first phi node should be the first statement in the basic-block. +// A number of loops rely on this behavior, so they don't need to walk through the whole list +// of instructions in a basic-block (e.g. the calls to destroyData in BasicBlock::~BasicBlock). struct Phi: Stmt { Temp *targetTemp; - struct Data { - QVector<Expr *> incoming; // used by Phi nodes - }; + VarLengthArray<Expr *, 4> incoming; - Data *d; - - Phi(int id): Stmt(id), d(0) {} + Phi(int id): Stmt(id) {} virtual void accept(StmtVisitor *v) { v->visitPhi(this); } virtual Phi *asPhi() { return this; } - void destroyData() { - delete d; - d = 0; - } + void destroyData() + { incoming.~VarLengthArray(); } }; struct Q_QML_PRIVATE_EXPORT Module { @@ -813,7 +836,17 @@ public: , _groupStart(false) , _isRemoved(false) {} - ~BasicBlock(); + + ~BasicBlock() + { + for (Stmt *s : qAsConst(_statements)) { + if (Phi *p = s->asPhi()) { + p->destroyData(); + } else { + break; + } + } + } const QVector<Stmt *> &statements() const { @@ -836,15 +869,73 @@ public: return i; } - void appendStatement(Stmt *statement); - void prependStatement(Stmt *stmt); - void prependStatements(const QVector<Stmt *> &stmts); - void insertStatementBefore(Stmt *before, Stmt *newStmt); - void insertStatementBefore(int index, Stmt *newStmt); - void insertStatementBeforeTerminator(Stmt *stmt); - void replaceStatement(int index, Stmt *newStmt); - void removeStatement(Stmt *stmt); - void removeStatement(int idx); + void appendStatement(Stmt *statement) + { + Q_ASSERT(!isRemoved()); + if (nextLocation.startLine) + statement->location = nextLocation; + _statements.append(statement); + } + + void prependStatement(Stmt *stmt) + { + Q_ASSERT(!isRemoved()); + _statements.prepend(stmt); + } + + void prependStatements(const QVector<Stmt *> &stmts) + { + Q_ASSERT(!isRemoved()); + QVector<Stmt *> newStmts = stmts; + newStmts += _statements; + _statements = newStmts; + } + + void insertStatementBefore(Stmt *before, Stmt *newStmt) + { + int idx = _statements.indexOf(before); + Q_ASSERT(idx >= 0); + _statements.insert(idx, newStmt); + } + + void insertStatementBefore(int index, Stmt *newStmt) + { + Q_ASSERT(index >= 0); + _statements.insert(index, newStmt); + } + + void insertStatementBeforeTerminator(Stmt *stmt) + { + Q_ASSERT(!isRemoved()); + _statements.insert(_statements.size() - 1, stmt); + } + + void replaceStatement(int index, Stmt *newStmt) + { + Q_ASSERT(!isRemoved()); + if (Phi *p = _statements[index]->asPhi()) { + p->destroyData(); + } + _statements[index] = newStmt; + } + + void removeStatement(Stmt *stmt) + { + Q_ASSERT(!isRemoved()); + if (Phi *p = stmt->asPhi()) { + p->destroyData(); + } + _statements.remove(_statements.indexOf(stmt)); + } + + void removeStatement(int idx) + { + Q_ASSERT(!isRemoved()); + if (Phi *p = _statements[idx]->asPhi()) { + p->destroyData(); + } + _statements.remove(idx); + } inline bool isEmpty() const { Q_ASSERT(!isRemoved()); @@ -1209,6 +1300,251 @@ protected: BasicBlock *currentBB; }; +inline unsigned BasicBlock::newTemp() +{ + Q_ASSERT(!isRemoved()); + return function->tempCount++; +} + +inline Temp *BasicBlock::TEMP(unsigned index) +{ + Q_ASSERT(!isRemoved()); + Temp *e = function->New<Temp>(); + e->init(Temp::VirtualRegister, index); + return e; +} + +inline ArgLocal *BasicBlock::ARG(unsigned index, unsigned scope) +{ + Q_ASSERT(!isRemoved()); + ArgLocal *e = function->New<ArgLocal>(); + e->init(scope ? ArgLocal::ScopedFormal : ArgLocal::Formal, index, scope); + return e; +} + +inline ArgLocal *BasicBlock::LOCAL(unsigned index, unsigned scope) +{ + Q_ASSERT(!isRemoved()); + ArgLocal *e = function->New<ArgLocal>(); + e->init(scope ? ArgLocal::ScopedLocal : ArgLocal::Local, index, scope); + return e; +} + +inline Expr *BasicBlock::CONST(Type type, double value) +{ + Q_ASSERT(!isRemoved()); + Const *e = function->New<Const>(); + if (type == NumberType) { + int ival = (int)value; + // +0 != -0, so we need to convert to double when negating 0 + if (ival == value && !(value == 0 && isNegative(value))) + type = SInt32Type; + else + type = DoubleType; + } else if (type == NullType) { + value = 0; + } else if (type == UndefinedType) { + value = qQNaN(); + } + + e->init(type, value); + return e; +} + +inline Expr *BasicBlock::STRING(const QString *value) +{ + Q_ASSERT(!isRemoved()); + String *e = function->New<String>(); + e->init(value); + return e; +} + +inline Expr *BasicBlock::REGEXP(const QString *value, int flags) +{ + Q_ASSERT(!isRemoved()); + RegExp *e = function->New<RegExp>(); + e->init(value, flags); + return e; +} + +inline Name *BasicBlock::NAME(const QString &id, quint32 line, quint32 column) +{ + Q_ASSERT(!isRemoved()); + Name *e = function->New<Name>(); + e->init(function->newString(id), line, column); + return e; +} + +inline Name *BasicBlock::GLOBALNAME(const QString &id, quint32 line, quint32 column) +{ + Q_ASSERT(!isRemoved()); + Name *e = function->New<Name>(); + e->initGlobal(function->newString(id), line, column); + return e; +} + + +inline Name *BasicBlock::NAME(Name::Builtin builtin, quint32 line, quint32 column) +{ + Q_ASSERT(!isRemoved()); + Name *e = function->New<Name>(); + e->init(builtin, line, column); + return e; +} + +inline Closure *BasicBlock::CLOSURE(int functionInModule) +{ + Q_ASSERT(!isRemoved()); + Closure *clos = function->New<Closure>(); + clos->init(functionInModule, function->module->functions.at(functionInModule)->name); + return clos; +} + +inline Expr *BasicBlock::CONVERT(Expr *expr, Type type) +{ + Q_ASSERT(!isRemoved()); + Convert *e = function->New<Convert>(); + e->init(expr, type); + return e; +} + +inline Expr *BasicBlock::UNOP(AluOp op, Expr *expr) +{ + Q_ASSERT(!isRemoved()); + Unop *e = function->New<Unop>(); + e->init(op, expr); + return e; +} + +inline Expr *BasicBlock::BINOP(AluOp op, Expr *left, Expr *right) +{ + Q_ASSERT(!isRemoved()); + Binop *e = function->New<Binop>(); + e->init(op, left, right); + return e; +} + +inline Expr *BasicBlock::CALL(Expr *base, ExprList *args) +{ + Q_ASSERT(!isRemoved()); + Call *e = function->New<Call>(); + e->init(base, args); + int argc = 0; + for (ExprList *it = args; it; it = it->next) + ++argc; + function->maxNumberOfArguments = qMax(function->maxNumberOfArguments, argc); + return e; +} + +inline Expr *BasicBlock::NEW(Expr *base, ExprList *args) +{ + Q_ASSERT(!isRemoved()); + New *e = function->New<New>(); + e->init(base, args); + return e; +} + +inline Expr *BasicBlock::SUBSCRIPT(Expr *base, Expr *index) +{ + Q_ASSERT(!isRemoved()); + Subscript *e = function->New<Subscript>(); + e->init(base, index); + return e; +} + +inline Expr *BasicBlock::MEMBER(Expr *base, const QString *name, QQmlPropertyData *property, uchar kind, int attachedPropertiesIdOrEnumValue) +{ + Q_ASSERT(!isRemoved()); + Member*e = function->New<Member>(); + e->init(base, name, property, kind, attachedPropertiesIdOrEnumValue); + return e; +} + +inline Stmt *BasicBlock::EXP(Expr *expr) +{ + Q_ASSERT(!isRemoved()); + if (isTerminated()) + return 0; + + Exp *s = function->NewStmt<Exp>(); + s->init(expr); + appendStatement(s); + return s; +} + +inline Stmt *BasicBlock::MOVE(Expr *target, Expr *source) +{ + Q_ASSERT(!isRemoved()); + if (isTerminated()) + return 0; + + Move *s = function->NewStmt<Move>(); + s->init(target, source); + appendStatement(s); + return s; +} + +inline Stmt *BasicBlock::JUMP(BasicBlock *target) +{ + Q_ASSERT(!isRemoved()); + if (isTerminated()) + return 0; + + Jump *s = function->NewStmt<Jump>(); + s->init(target); + appendStatement(s); + + Q_ASSERT(! out.contains(target)); + out.append(target); + + Q_ASSERT(! target->in.contains(this)); + target->in.append(this); + + return s; +} + +inline Stmt *BasicBlock::CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse) +{ + Q_ASSERT(!isRemoved()); + if (isTerminated()) + return 0; + + if (iftrue == iffalse) { + MOVE(TEMP(newTemp()), cond); + return JUMP(iftrue); + } + + CJump *s = function->NewStmt<CJump>(); + s->init(cond, iftrue, iffalse, this); + appendStatement(s); + + Q_ASSERT(! out.contains(iftrue)); + out.append(iftrue); + + Q_ASSERT(! iftrue->in.contains(this)); + iftrue->in.append(this); + + Q_ASSERT(! out.contains(iffalse)); + out.append(iffalse); + + Q_ASSERT(! iffalse->in.contains(this)); + iffalse->in.append(this); + + return s; +} + +inline Stmt *BasicBlock::RET(Expr *expr) +{ + Q_ASSERT(!isRemoved()); + if (isTerminated()) + return 0; + + Ret *s = function->NewStmt<Ret>(); + s->init(expr); + appendStatement(s); + return s; +} + } // end of namespace IR } // end of namespace QV4 diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp index 7881ab951a..6a4c1c54d6 100644 --- a/src/qml/compiler/qv4ssa.cpp +++ b/src/qml/compiler/qv4ssa.cpp @@ -56,7 +56,6 @@ #include <cmath> #include <iostream> #include <cassert> -#include <algorithm> QT_USE_NAMESPACE @@ -87,120 +86,6 @@ static void showMeTheCode(IR::Function *function, const char *marker) } } -#if !defined(BROKEN_STD_VECTOR_BOOL_OR_BROKEN_STD_FIND) -// Sanity: -class BitVector -{ - std::vector<bool> bits; - -public: - BitVector(int size = 0, bool value = false) - : bits(size, value) - {} - - void reserve(int size) - { bits.reserve(size); } - - int size() const - { - Q_ASSERT(bits.size() < INT_MAX); - return static_cast<int>(bits.size()); - } - - void resize(int newSize) - { bits.resize(newSize); } - - void assign(int newSize, bool value) - { bits.assign(newSize, value); } - - int findNext(int start, bool value, bool wrapAround) const - { - // The ++operator of std::vector<bool>::iterator in libc++ has a bug when using it on an - // iterator pointing to the last element. It will not be set to ::end(), but beyond - // that. (It will be set to the first multiple of the native word size that is bigger - // than size().) - // - // See http://llvm.org/bugs/show_bug.cgi?id=19663 - // - // The work-around is to calculate the distance, and compare it to the size() to see if it's - // beyond the end, or take the minimum of the distance and the size. - - size_t pos = std::distance(bits.begin(), - std::find(bits.begin() + start, bits.end(), value)); - if (wrapAround && pos >= static_cast<size_t>(size())) - pos = std::distance(bits.begin(), - std::find(bits.begin(), bits.begin() + start, value)); - - pos = qMin(pos, static_cast<size_t>(size())); - - Q_ASSERT(pos <= static_cast<size_t>(size())); - Q_ASSERT(pos < INT_MAX); - - return static_cast<int>(pos); - } - - bool at(int idx) const - { return bits.at(idx); } - - void setBit(int idx) - { bits[idx] = true; } - - void clearBit(int idx) - { bits[idx] = false; } -}; -#else // Insanity: -class BitVector -{ - QBitArray bits; - -public: - BitVector(int size = 0, bool value = false) - : bits(size, value) - {} - - void reserve(int size) - { Q_UNUSED(size); } - - int size() const - { return bits.size(); } - - void resize(int newSize) - { bits.resize(newSize); } - - void assign(int newSize, bool value) - { - bits.resize(newSize); - bits.fill(value); - } - - int findNext(int start, bool value, bool wrapAround) const - { - for (int i = start, ei = size(); i < ei; ++i) { - if (at(i) == value) - return i; - } - - if (wrapAround) { - for (int i = 0, ei = start; i < ei; ++i) { - if (at(i) == value) - return i; - } - } - - return size(); - } - - bool at(int idx) const - { return bits.at(idx); } - - void setBit(int idx) - { bits[idx] = true; } - - void clearBit(int idx) - { bits[idx] = false; } -}; -#endif - class ProcessedBlocks { BitVector processed; @@ -557,7 +442,7 @@ class DominatorTree BasicBlockIndex p = d->parent[n]; BasicBlockIndex s = p; - foreach (BasicBlock *v, function->basicBlock(n)->in) { + for (BasicBlock *v : function->basicBlock(n)->in) { BasicBlockIndex ss = InvalidBasicBlockIndex; if (d->dfnum[v->index()] <= d->dfnum[n]) ss = v->index(); @@ -617,7 +502,7 @@ public: // compute children of each node in the dominator tree std::vector<std::vector<BasicBlockIndex> > children; // BasicBlock index -> children children.resize(function->basicBlockCount()); - foreach (BasicBlock *n, function->basicBlocks()) { + for (BasicBlock *n : function->basicBlocks()) { if (n->isRemoved()) continue; const BasicBlockIndex nodeIndex = n->index(); @@ -633,7 +518,7 @@ public: nodeStatus.resize(function->basicBlockCount()); std::vector<BasicBlockIndex> worklist; worklist.reserve(function->basicBlockCount()); - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) continue; BasicBlockIndex nodeIndex = bb->index(); @@ -667,7 +552,7 @@ public: if (np.todo.empty()) { BasicBlockSet &S = DF[node]; S.init(function); - foreach (BasicBlock *y, function->basicBlock(node)->out) + for (BasicBlock *y : function->basicBlock(node)->out) if (idom[y->index()] != node) S.insert(y); for (BasicBlockIndex child : np.children) { @@ -689,7 +574,7 @@ public: buf.open(QIODevice::WriteOnly); QTextStream qout(&buf); qout << "Dominator Frontiers:" << endl; - foreach (BasicBlock *n, function->basicBlocks()) { + for (BasicBlock *n : function->basicBlocks()) { if (n->isRemoved()) continue; @@ -706,7 +591,7 @@ public: } if (DebugDominatorFrontiers && DebugCodeCanUseLotsOfCpu) { - foreach (BasicBlock *n, function->basicBlocks()) { + for (BasicBlock *n : function->basicBlocks()) { if (n->isRemoved()) continue; const BasicBlockSet &fBlocks = DF[n->index()]; @@ -714,7 +599,7 @@ public: BasicBlock *fBlock = *it; Q_ASSERT(!dominates(n, fBlock) || fBlock == n); bool hasDominatedSucc = false; - foreach (BasicBlock *succ, fBlock->in) { + for (BasicBlock *succ : fBlock->in) { if (dominates(n, succ)) { hasDominatedSucc = true; break; @@ -747,7 +632,7 @@ public: buf.open(QIODevice::WriteOnly); QTextStream qout(&buf); qout << "Immediate dominators:" << endl; - foreach (BasicBlock *to, function->basicBlocks()) { + for (BasicBlock *to : function->basicBlocks()) { if (to->isRemoved()) continue; @@ -881,7 +766,7 @@ private: { std::vector<int> nodeDepths(size_t(function->basicBlockCount()), -1); nodeDepths[0] = 0; - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) continue; @@ -945,8 +830,7 @@ private: std::vector<BasicBlockIndex> prefix; prefix.reserve(32); - for (int i = 0, ei = node->in.size(); i != ei; ++i) { - BasicBlock *in = node->in.at(i); + for (BasicBlock *in : node->in) { if (node == in) // back-edge to self continue; if (dominates(node->index(), in->index())) // a known back-edge @@ -1055,13 +939,13 @@ public: for (size_t i = 0; i != ei; ++i) A_orig[i].reserve(8); - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) continue; currentBB = bb; killed.assign(function->tempCount, false); - foreach (Stmt *s, bb->statements()) + for (Stmt *s : bb->statements()) s->accept(this); } } @@ -1381,16 +1265,15 @@ public: void insertPhiNode(const Temp &a, BasicBlock *y, IR::Function *f) { Phi *phiNode = f->NewStmt<Phi>(); - phiNode->d = new Phi::Data; phiNode->targetTemp = f->New<Temp>(); phiNode->targetTemp->init(a.kind, a.index); y->prependStatement(phiNode); - phiNode->d->incoming.resize(y->in.size()); + phiNode->incoming.resize(y->in.size()); for (int i = 0, ei = y->in.size(); i < ei; ++i) { Temp *t = f->New<Temp>(); t->init(a.kind, a.index); - phiNode->d->incoming[i] = t; + phiNode->incoming[i] = t; } } @@ -1565,7 +1448,7 @@ private: processed.markAsProcessed(bb); BasicBlock *next = 0; - foreach (BasicBlock *out, bb->out) { + for (BasicBlock *out : bb->out) { if (processed.alreadyProcessed(out)) continue; if (!next) @@ -1581,17 +1464,17 @@ private: { currentBB = bb; - foreach (Stmt *s, bb->statements()) { + for (Stmt *s : bb->statements()) { currentStmt = s; s->accept(this); } - foreach (BasicBlock *Y, bb->out) { + for (BasicBlock *Y : bb->out) { const int j = Y->in.indexOf(bb); Q_ASSERT(j >= 0 && j < Y->in.size()); - foreach (Stmt *s, Y->statements()) { + for (Stmt *s : Y->statements()) { if (Phi *phi = s->asPhi()) { - Temp *t = phi->d->incoming[j]->asTemp(); + Temp *t = phi->incoming[j]->asTemp(); unsigned newTmp = currentNumber(*t); // qDebug()<<"I: replacing phi use"<<a<<"with"<<newTmp<<"in L"<<Y->index; t->index = newTmp; @@ -1845,11 +1728,11 @@ public: { grow(); - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) continue; - foreach (Stmt *s, bb->statements()) { + for (Stmt *s : bb->statements()) { if (!s) continue; @@ -1905,7 +1788,7 @@ public: void applyToFunction() { - foreach (BasicBlock *bb, theFunction->basicBlocks()) { + for (BasicBlock *bb : theFunction->basicBlocks()) { if (bb->isRemoved()) continue; @@ -1979,6 +1862,11 @@ public: return worklistSize == 0; } + unsigned size() const + { + return worklistSize; + } + Stmt *takeNext(Stmt *last) { if (isEmpty()) @@ -2185,27 +2073,6 @@ protected: } }; -struct DiscoveredType { - int type; - MemberExpressionResolver *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); } - - bool operator!=(Type other) const { return type != other; } - bool operator==(Type other) const { return type == other; } - bool operator==(const DiscoveredType &other) const { return type == other.type; } - bool operator!=(const DiscoveredType &other) const { return type != other.type; } -}; - class PropagateTempTypes: public StmtVisitor, ExprVisitor { const DefUses &defUses; @@ -2274,7 +2141,7 @@ protected: virtual void visitRet(Ret *s) { s->expr->accept(this); } virtual void visitPhi(Phi *s) { s->targetTemp->accept(this); - foreach (Expr *e, s->d->incoming) + foreach (Expr *e, s->incoming) e->accept(this); } }; @@ -2306,6 +2173,7 @@ class TypeInference: public StmtVisitor, public ExprVisitor {} }; TypingResult _ty; + Stmt *_currentStmt; public: TypeInference(QQmlEnginePrivate *qmlEngine, const DefUses &defUses) @@ -2314,6 +2182,7 @@ public: , _tempTypes(_defUses.tempCount()) , _worklist(0) , _ty(UnknownType) + , _currentStmt(nullptr) {} void run(StatementWorklist &w) { @@ -2330,7 +2199,10 @@ public: QTextStream qout(&buf); qout<<"Typing stmt "; IRPrinter(&qout).print(s); + qout.flush(); qDebug("%s", buf.data().constData()); + + qDebug("%u left in the worklist", _worklist->size()); } if (!run(s)) { @@ -2341,6 +2213,7 @@ public: QTextStream qout(&buf); qout<<"Pushing back stmt: "; IRPrinter(&qout).print(s); + qout.flush(); qDebug("%s", buf.data().constData()); } } else { @@ -2350,6 +2223,7 @@ public: QTextStream qout(&buf); qout<<"Finished: "; IRPrinter(&qout).print(s); + qout.flush(); qDebug("%s", buf.data().constData()); } } @@ -2373,7 +2247,9 @@ private: bool run(Stmt *s) { TypingResult ty; std::swap(_ty, ty); - s->accept(this); + std::swap(_currentStmt, s); + _currentStmt->accept(this); + std::swap(_currentStmt, s); std::swap(_ty, ty); return ty.fullyTyped; } @@ -2407,11 +2283,16 @@ private: QTextStream qout(&buf); qout << "Pushing back dependent stmt: "; IRPrinter(&qout).print(s); + qout.flush(); qDebug("%s", buf.data().constData()); } } - *_worklist += _defUses.uses(*t); + for (Stmt *s : qAsConst(_defUses.uses(*t))) { + if (s != _currentStmt) { + *_worklist += s; + } + } } } else { e->type = (Type) ty.type; @@ -2547,7 +2428,7 @@ protected: if (_ty.fullyTyped && _ty.type.memberResolver && _ty.type.memberResolver->isValid()) { MemberExpressionResolver *resolver = _ty.type.memberResolver; - _ty.type.type = resolver->resolveMember(qmlEngine, resolver, e); + _ty.type = resolver->resolveMember(qmlEngine, resolver, e); } else _ty.type = VarType; } @@ -2569,9 +2450,9 @@ protected: virtual void visitCJump(CJump *s) { _ty = run(s->cond); } virtual void visitRet(Ret *s) { _ty = run(s->expr); } virtual void visitPhi(Phi *s) { - _ty = run(s->d->incoming[0]); - for (int i = 1, ei = s->d->incoming.size(); i != ei; ++i) { - TypingResult ty = run(s->d->incoming[i]); + _ty = run(s->incoming[0]); + for (int i = 1, ei = s->incoming.size(); i != ei; ++i) { + TypingResult ty = run(s->incoming[i]); if (!ty.fullyTyped && _ty.fullyTyped) { // When one of the temps not fully typed, we already know that we cannot completely type this node. // So, pick the type we calculated upto this point, and wait until the unknown one will be typed. @@ -2834,12 +2715,12 @@ public: void run(IR::Function *f, StatementWorklist &worklist) { _f = f; - foreach (BasicBlock *bb, f->basicBlocks()) { + for (BasicBlock *bb : f->basicBlocks()) { if (bb->isRemoved()) continue; _conversions.clear(); - foreach (Stmt *s, bb->statements()) { + for (Stmt *s : bb->statements()) { _currStmt = s; s->accept(this); } @@ -2890,7 +2771,7 @@ public: _defUses.addUse(*source, conversion.stmt); if (Phi *phi = conversion.stmt->asPhi()) { - int idx = phi->d->incoming.indexOf(t); + int idx = phi->incoming.indexOf(t); Q_ASSERT(idx != -1); bb->in[idx]->insertStatementBeforeTerminator(convCall); } else { @@ -3042,14 +2923,15 @@ protected: virtual void visitRet(Ret *s) { run(s->expr); } virtual void visitPhi(Phi *s) { Type ty = s->targetTemp->type; - for (int i = 0, ei = s->d->incoming.size(); i != ei; ++i) - run(s->d->incoming[i], ty); + for (int i = 0, ei = s->incoming.size(); i != ei; ++i) + run(s->incoming[i], ty); } }; void splitCriticalEdges(IR::Function *f, DominatorTree &df, StatementWorklist &worklist, DefUses &defUses) { - foreach (BasicBlock *toBB, f->basicBlocks()) { + const QVector<BasicBlock *> copy = f->basicBlocks(); + for (BasicBlock *toBB : copy) { if (toBB->isRemoved()) continue; if (toBB->in.size() < 2) @@ -3117,7 +2999,7 @@ void splitCriticalEdges(IR::Function *f, DominatorTree &df, StatementWorklist &w df.setImmediateDominator(newBB, fromBB); bool toNeedsNewIdom = true; - foreach (BasicBlock *bb, toBB->in) { + for (BasicBlock *bb : toBB->in) { if (bb != newBB && !df.dominates(toBB, bb)) { toNeedsNewIdom = false; break; @@ -3227,7 +3109,7 @@ public: backedges.clear(); - foreach (BasicBlock *in, bb->in) + for (BasicBlock *in : bb->in) if (dt.dominates(bb, in)) backedges.push_back(in); @@ -3304,7 +3186,7 @@ private: // those predecessors are not in the current subloop. It might be the case // that they are in other loops, which we will then add as a subloop to the // current loop. - foreach (BasicBlock *predIn, predIt->in) + for (BasicBlock *predIn : predIt->in) if (predIn->containingGroup() != subloop) worklist.push_back(predIn); } else { @@ -3315,7 +3197,7 @@ private: predIt->setContainingGroup(loopHead); // Add all incoming edges to the worklist. - foreach (BasicBlock *bb, predIt->in) + for (BasicBlock *bb : predIt->in) worklist.push_back(bb); } } @@ -3327,7 +3209,7 @@ private: void createLoopInfos(IR::Function *function) { - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) continue; if (BasicBlock *loopHeader = bb->containingGroup()) @@ -3400,7 +3282,7 @@ class BlockScheduler { Q_ASSERT(candidate->containingGroup() == currentGroup.group); - foreach (BasicBlock *in, candidate->in) { + for (BasicBlock *in : candidate->in) { if (emitted.alreadyProcessed(in)) continue; @@ -3510,7 +3392,7 @@ public: void checkCriticalEdges(QVector<BasicBlock *> basicBlocks) { foreach (BasicBlock *bb, basicBlocks) { if (bb && bb->out.size() > 1) { - foreach (BasicBlock *bb2, bb->out) { + for (BasicBlock *bb2 : bb->out) { if (bb2 && bb2->in.size() > 1) { qDebug() << "found critical edge between block" << bb->index() << "and block" << bb2->index(); @@ -3545,28 +3427,28 @@ static void cleanupBasicBlocks(IR::Function *function) reachableBlocks.setBit(bb->index()); - foreach (BasicBlock *outBB, bb->out) { + for (BasicBlock *outBB : bb->out) { if (!reachableBlocks.at(outBB->index())) postponed.append(outBB); } } - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) // the block has already been removed, so ignore it continue; if (reachableBlocks.at(bb->index())) // the block is reachable, so ignore it continue; - foreach (BasicBlock *outBB, bb->out) { + for (BasicBlock *outBB : bb->out) { if (outBB->isRemoved() || !reachableBlocks.at(outBB->index())) continue; // We do not need to unlink from blocks that are scheduled to be removed. int idx = outBB->in.indexOf(bb); if (idx != -1) { outBB->in.remove(idx); - foreach (Stmt *s, outBB->statements()) { + for (Stmt *s : outBB->statements()) { if (Phi *phi = s->asPhi()) - phi->d->incoming.remove(idx); + phi->incoming.remove(idx); else break; } @@ -3581,9 +3463,9 @@ static void cleanupBasicBlocks(IR::Function *function) inline Const *isConstPhi(Phi *phi) { - if (Const *c = phi->d->incoming[0]->asConst()) { - for (int i = 1, ei = phi->d->incoming.size(); i != ei; ++i) { - if (Const *cc = phi->d->incoming[i]->asConst()) { + if (Const *c = phi->incoming[0]->asConst()) { + for (int i = 1, ei = phi->incoming.size(); i != ei; ++i) { + if (Const *cc = phi->incoming[i]->asConst()) { if (c->value != cc->value) return 0; if (!(c->type == cc->type || (c->type & NumberType && cc->type & NumberType))) @@ -3684,8 +3566,8 @@ protected: virtual void visitCJump(CJump *s) { check(s->cond); } virtual void visitRet(Ret *s) { check(s->expr); } virtual void visitPhi(Phi *s) { - for (int i = 0, ei = s->d->incoming.size(); i != ei; ++i) - check(s->d->incoming[i]); + for (int i = 0, ei = s->incoming.size(); i != ei; ++i) + check(s->incoming[i]); } private: @@ -3746,11 +3628,11 @@ void unlink(BasicBlock *from, BasicBlock *to, IR::Function *func, DefUses &defUs if (!outStmt) continue; if (Phi *phi = outStmt->asPhi()) { - if (Temp *t = phi->d->incoming[idx]->asTemp()) { + if (Temp *t = phi->incoming[idx]->asTemp()) { defUses.removeUse(phi, *t); W += defUses.defStmt(*t); } - phi->d->incoming.remove(idx); + phi->incoming.remove(idx); W += phi; } else { break; @@ -3800,14 +3682,14 @@ void unlink(BasicBlock *from, BasicBlock *to, IR::Function *func, DefUses &defUs continue; // unlink all incoming edges - foreach (BasicBlock *in, bb->in) { + for (BasicBlock *in : bb->in) { int idx = in->out.indexOf(bb); if (idx != -1) in->out.remove(idx); } // unlink all outgoing edges, including "arguments" to phi statements - foreach (BasicBlock *out, bb->out) { + for (BasicBlock *out : bb->out) { if (out->isRemoved()) continue; @@ -3823,7 +3705,7 @@ void unlink(BasicBlock *from, BasicBlock *to, IR::Function *func, DefUses &defUs } // unlink all defs/uses from the statements in the basic block - foreach (Stmt *s, bb->statements()) { + for (Stmt *s : bb->statements()) { if (!s) continue; @@ -3938,7 +3820,7 @@ void cfg2dot(IR::Function *f, const QVector<LoopDetection::LoopInfo *> &loops = Util(qout).genLoop(l); } - foreach (BasicBlock *bb, f->basicBlocks()) { + for (BasicBlock *bb : f->basicBlocks()) { if (bb->isRemoved()) continue; @@ -3949,7 +3831,7 @@ void cfg2dot(IR::Function *f, const QVector<LoopDetection::LoopInfo *> &loops = else qout << ", shape=circle"; qout << "];\n"; - foreach (BasicBlock *out, bb->out) + for (BasicBlock *out : bb->out) qout << " L" << idx << " -> L" << out->index() << "\n"; } @@ -3987,9 +3869,9 @@ void optimizeSSA(StatementWorklist &W, DefUses &defUses, DominatorTree &df) } // copy propagation: - if (phi->d->incoming.size() == 1) { + if (phi->incoming.size() == 1) { Temp *t = phi->targetTemp; - Expr *e = phi->d->incoming.first(); + Expr *e = phi->incoming.first(); QVector<Stmt *> newT2Uses; replaceUses(t, e, W, &newT2Uses); @@ -4420,14 +4302,14 @@ private: void buildIntervals(BasicBlock *bb, BasicBlock *loopEnd) { LiveRegs live; - foreach (BasicBlock *successor, bb->out) { + for (BasicBlock *successor : bb->out) { live.unite(_liveIn[successor->index()]); const int bbIndex = successor->in.indexOf(bb); Q_ASSERT(bbIndex >= 0); - foreach (Stmt *s, successor->statements()) { + for (Stmt *s : successor->statements()) { if (Phi *phi = s->asPhi()) { - if (Temp *t = phi->d->incoming.at(bbIndex)->asTemp()) + if (Temp *t = phi->incoming.at(bbIndex)->asTemp()) live.insert(*t); } else { break; @@ -4435,7 +4317,7 @@ private: } } - QVector<Stmt *> statements = bb->statements(); + const QVector<Stmt *> &statements = bb->statements(); foreach (const Temp &opd, live) interval(&opd).addRange(start(bb), end(bb)); @@ -4483,7 +4365,7 @@ void removeUnreachleBlocks(IR::Function *function) { QVector<BasicBlock *> newSchedule; newSchedule.reserve(function->basicBlockCount()); - foreach (BasicBlock *bb, function->basicBlocks()) + for (BasicBlock *bb : function->basicBlocks()) if (!bb->isRemoved()) newSchedule.append(bb); function->setScheduledBlocks(newSchedule); @@ -4528,9 +4410,9 @@ public: } } - foreach (BasicBlock *bb, function->basicBlocks()) + for (BasicBlock *bb : function->basicBlocks()) if (!bb->isRemoved()) - foreach (Stmt *s, bb->statements()) + for (Stmt *s : bb->statements()) s->accept(this); if (convertArgs && function->formals.size() > 0) @@ -4614,7 +4496,7 @@ public: { block = new BasicBlock(originalBlock->function, 0); - foreach (Stmt *s, originalBlock->statements()) { + for (Stmt *s : originalBlock->statements()) { s->accept(this); clonedStmt->location = s->location; } @@ -4644,9 +4526,8 @@ protected: clonedStmt = phi; phi->targetTemp = clone(stmt->targetTemp); - phi->d = new Phi::Data; - foreach (Expr *in, stmt->d->incoming) - phi->d->incoming.append(clone(in)); + foreach (Expr *in, stmt->incoming) + phi->incoming.append(clone(in)); block->appendStatement(phi); } @@ -4731,7 +4612,8 @@ private: // the terminators will automatically insert that edge). The blocks where the originals // pointed to will have an extra incoming edge from the copied blocks. - foreach (BasicBlock *in, loop->loopHeader->in) { + BasicBlock::IncomingEdges inCopy = loop->loopHeader->in; + for (BasicBlock *in : inCopy) { if (unpeeled.loopHeader != in // this can happen for really tight loops (where there are no body blocks). This is a back-edge in that case. && !unpeeled.loopBody.contains(in) // if the edge is not coming from within the copied set, leave it alone && !dt.dominates(loop->loopHeader, in)) // an edge coming from within the loop (so a back-edge): this is handled when rewiring all outgoing edges @@ -4805,7 +4687,7 @@ static void verifyCFG(IR::Function *function) if (!DoVerification) return; - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) { Q_ASSERT(bb->in.isEmpty()); Q_ASSERT(bb->out.isEmpty()); @@ -4837,14 +4719,14 @@ static void verifyCFG(IR::Function *function) } // Check the outgoing edges: - foreach (BasicBlock *out, bb->out) { + for (BasicBlock *out : bb->out) { Q_UNUSED(out); Q_ASSERT(!out->isRemoved()); Q_ASSERT(out->in.contains(bb)); } // Check the incoming edges: - foreach (BasicBlock *in, bb->in) { + for (BasicBlock *in : bb->in) { Q_UNUSED(in); Q_ASSERT(!in->isRemoved()); Q_ASSERT(in->out.contains(bb)); @@ -4861,7 +4743,7 @@ static void verifyImmediateDominators(const DominatorTree &dt, IR::Function *fun dt.dumpImmediateDominators(); DominatorTree referenceTree(function); - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) continue; @@ -4882,11 +4764,11 @@ static void verifyNoPointerSharing(IR::Function *function) public: void operator()(IR::Function *f) { - foreach (BasicBlock *bb, f->basicBlocks()) { + for (BasicBlock *bb : f->basicBlocks()) { if (bb->isRemoved()) continue; - foreach (Stmt *s, bb->statements()) + for (Stmt *s : bb->statements()) s->accept(this); } } @@ -4901,7 +4783,7 @@ static void verifyNoPointerSharing(IR::Function *function) { check(s); s->targetTemp->accept(this); - foreach (Expr *e, s->d->incoming) + foreach (Expr *e, s->incoming) e->accept(this); } @@ -4950,11 +4832,11 @@ class RemoveLineNumbers: public SideEffectsChecker, public StmtVisitor public: static void run(IR::Function *function) { - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) continue; - foreach (Stmt *s, bb->statements()) { + for (Stmt *s : bb->statements()) { if (!hasSideEffects(s)) { s->location = QQmlJS::AST::SourceLocation(); } @@ -5166,13 +5048,13 @@ LifeTimeIntervals::LifeTimeIntervals(IR::Function *function) // basic-block. void LifeTimeIntervals::renumber(IR::Function *function) { - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) continue; _basicBlockPosition[bb->index()].start = _lastPosition + 1; - foreach (Stmt *s, bb->statements()) { + for (Stmt *s : bb->statements()) { if (s->asPhi()) continue; @@ -5202,7 +5084,7 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee function->removeSharedExpressions(); int statementCount = 0; - foreach (BasicBlock *bb, function->basicBlocks()) + for (BasicBlock *bb : function->basicBlocks()) if (!bb->isRemoved()) statementCount += bb->statementCount(); // showMeTheCode(function); @@ -5332,15 +5214,15 @@ void Optimizer::convertOutOfSSA() { // There should be no critical edges at this point. - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { MoveMapping moves; - foreach (BasicBlock *successor, bb->out) { + for (BasicBlock *successor : bb->out) { const int inIdx = successor->in.indexOf(bb); Q_ASSERT(inIdx >= 0); - foreach (Stmt *s, successor->statements()) { + for (Stmt *s : successor->statements()) { if (Phi *phi = s->asPhi()) { - moves.add(clone(phi->d->incoming[inIdx], function), + moves.add(clone(phi->incoming[inIdx], function), clone(phi->targetTemp, function)->asTemp()); } else { break; @@ -5368,7 +5250,7 @@ void Optimizer::convertOutOfSSA() { moves.insertMoves(bb, function, true); } - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { while (!bb->isEmpty()) { if (bb->statements().first()->asPhi()) { bb->removeStatement(0); diff --git a/src/qml/debugger/qqmlabstractprofileradapter_p.h b/src/qml/debugger/qqmlabstractprofileradapter_p.h index bd93da324d..1104608055 100644 --- a/src/qml/debugger/qqmlabstractprofileradapter_p.h +++ b/src/qml/debugger/qqmlabstractprofileradapter_p.h @@ -64,6 +64,8 @@ class Q_QML_PRIVATE_EXPORT QQmlAbstractProfilerAdapter : public QObject, public Q_OBJECT public: + static const int s_numMessagesPerBatch = 1000; + QQmlAbstractProfilerAdapter(QObject *parent = 0) : QObject(parent), service(0), waiting(true), featuresEnabled(0) {} virtual ~QQmlAbstractProfilerAdapter() {} diff --git a/src/qml/debugger/qqmldebug.cpp b/src/qml/debugger/qqmldebug.cpp index 64a951d53b..9276bd0544 100644 --- a/src/qml/debugger/qqmldebug.cpp +++ b/src/qml/debugger/qqmldebug.cpp @@ -134,22 +134,11 @@ void QQmlDebuggingEnabler::setServices(const QStringList &services) */ bool QQmlDebuggingEnabler::startTcpDebugServer(int port, StartMode mode, const QString &hostName) { -#ifndef QQML_NO_DEBUG_PROTOCOL - QQmlDebugConnector::setPluginKey(QLatin1String("QQmlDebugServer")); - QQmlDebugConnector *connector = QQmlDebugConnector::instance(); - if (connector) { - QVariantHash configuration; - configuration[QLatin1String("portFrom")] = configuration[QLatin1String("portTo")] = port; - configuration[QLatin1String("block")] = (mode == WaitForClient); - configuration[QLatin1String("hostAddress")] = hostName; - return connector->open(configuration); - } -#else - Q_UNUSED(port); - Q_UNUSED(mode); - Q_UNUSED(hostName); -#endif - return false; + QVariantHash configuration; + configuration[QLatin1String("portFrom")] = configuration[QLatin1String("portTo")] = port; + configuration[QLatin1String("block")] = (mode == WaitForClient); + configuration[QLatin1String("hostAddress")] = hostName; + return startDebugConnector(QLatin1String("QQmlDebugServer"), configuration); } /*! @@ -164,18 +153,33 @@ bool QQmlDebuggingEnabler::startTcpDebugServer(int port, StartMode mode, const Q */ bool QQmlDebuggingEnabler::connectToLocalDebugger(const QString &socketFileName, StartMode mode) { + QVariantHash configuration; + configuration[QLatin1String("fileName")] = socketFileName; + configuration[QLatin1String("block")] = (mode == WaitForClient); + return startDebugConnector(QLatin1String("QQmlDebugServer"), configuration); +} + +/*! + * \since 5.7 + * + * Enables debugging for QML engines created after calling this function. A debug connector plugin + * specified by \a pluginName will be loaded and started using the given \a configuration. Supported + * configuration entries and their semantics depend on the plugin being loaded. You can only start + * one debug connector at a time. A debug connector may have already been started if the + * -qmljsdebugger= command line argument was given. This method returns \c true if a new debug + * connector was successfully started, or \c false otherwise. + */ +bool QQmlDebuggingEnabler::startDebugConnector(const QString &pluginName, + const QVariantHash &configuration) +{ #ifndef QQML_NO_DEBUG_PROTOCOL - QQmlDebugConnector::setPluginKey(QLatin1String("QQmlDebugServer")); + QQmlDebugConnector::setPluginKey(pluginName); QQmlDebugConnector *connector = QQmlDebugConnector::instance(); - if (connector) { - QVariantHash configuration; - configuration[QLatin1String("fileName")] = socketFileName; - configuration[QLatin1String("block")] = (mode == WaitForClient); + if (connector) return connector->open(configuration); - } #else - Q_UNUSED(fileName); - Q_UNUSED(mode); + Q_UNUSED(pluginName); + Q_UNUSED(configuration); #endif return false; } diff --git a/src/qml/debugger/qqmldebug.h b/src/qml/debugger/qqmldebug.h index eebebefe62..660b9e4d46 100644 --- a/src/qml/debugger/qqmldebug.h +++ b/src/qml/debugger/qqmldebug.h @@ -42,6 +42,7 @@ #include <QtQml/qtqmlglobal.h> #include <QtCore/qstring.h> +#include <QtCore/qvariant.h> QT_BEGIN_NAMESPACE @@ -65,6 +66,8 @@ struct Q_QML_EXPORT QQmlDebuggingEnabler const QString &hostName = QString()); static bool connectToLocalDebugger(const QString &socketFileName, StartMode mode = DoNotWaitForClient); + static bool startDebugConnector(const QString &pluginName, + const QVariantHash &configuration = QVariantHash()); }; // Execute code in constructor before first QQmlEngine is instantiated diff --git a/src/qml/debugger/qqmldebugconnector.cpp b/src/qml/debugger/qqmldebugconnector.cpp index 6edd28ea01..e6d1a218ad 100644 --- a/src/qml/debugger/qqmldebugconnector.cpp +++ b/src/qml/debugger/qqmldebugconnector.cpp @@ -127,18 +127,15 @@ QQmlDebugConnector *QQmlDebugConnector::instance() } if (!params->instance) { - const QString serverConnector = QStringLiteral("QQmlDebugServer"); - const QString nativeConnector = QStringLiteral("QQmlNativeDebugConnector"); - const bool isNative = params->arguments.startsWith(QLatin1String("native")); if (!params->pluginKey.isEmpty()) { - if (params->pluginKey == serverConnector || params->pluginKey == nativeConnector) - params->instance = loadQQmlDebugConnector(params->pluginKey); - else - return 0; // We cannot load anything else, yet + params->instance = loadQQmlDebugConnector(params->pluginKey); } else if (params->arguments.isEmpty()) { return 0; // no explicit class name given and no command line arguments } else { - params->instance = loadQQmlDebugConnector(isNative ? nativeConnector : serverConnector); + params->instance = loadQQmlDebugConnector( + params->arguments.startsWith(QLatin1String("native")) ? + QStringLiteral("QQmlNativeDebugConnector") : + QStringLiteral("QQmlDebugServer")); } if (params->instance) { diff --git a/src/qml/doc/src/qmltypereference.qdoc b/src/qml/doc/src/qmltypereference.qdoc index 31133c862f..f32574fcc1 100644 --- a/src/qml/doc/src/qmltypereference.qdoc +++ b/src/qml/doc/src/qmltypereference.qdoc @@ -55,7 +55,7 @@ are also provided by the \c QtQuick namespace which may be imported as follows: \qml -import QtQuick 2.5 +import QtQuick 2.7 \endqml See the \l{Qt Quick} module documentation for more information about the \c diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp index a6e085a913..131e0a5b0a 100644 --- a/src/qml/jit/qv4regalloc.cpp +++ b/src/qml/jit/qv4regalloc.cpp @@ -180,9 +180,9 @@ public: _calls.reserve(function->statementCount() / 3); _hints.resize(function->tempCount); - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { _currentBB = bb; - foreach (Stmt *s, bb->statements()) { + for (Stmt *s : bb->statements()) { _currentStmt = s; s->accept(this); } @@ -702,8 +702,8 @@ protected: // IRDecoder virtual void visitPhi(IR::Phi *s) { addDef(s->targetTemp, true); - for (int i = 0, ei = s->d->incoming.size(); i < ei; ++i) { - Expr *e = s->d->incoming.at(i); + for (int i = 0, ei = s->incoming.size(); i < ei; ++i) { + Expr *e = s->incoming.at(i); if (Temp *t = e->asTemp()) { // The actual use of an incoming value in a phi node is right before the terminator // of the other side of the incoming edge. @@ -821,8 +821,8 @@ class ResolutionPhase: protected StmtVisitor, protected ExprVisitor { const QVector<const RegisterInfo *> &_fpRegs; Stmt *_currentStmt; - QVector<Move *> _loads; - QVector<Move *> _stores; + std::vector<Move *> _loads; + std::vector<Move *> _stores; QHash<BasicBlock *, QList<const LifeTimeInterval *> > _liveAtStart; QHash<BasicBlock *, QList<const LifeTimeInterval *> > _liveAtEnd; @@ -872,7 +872,7 @@ private: { QVector<Stmt *> newStatements; - foreach (BasicBlock *bb, _function->basicBlocks()) { + for (BasicBlock *bb : _function->basicBlocks()) { _currentStmt = 0; QVector<Stmt *> statements = bb->statements(); @@ -892,13 +892,13 @@ private: else addNewIntervals(defPosition(_currentStmt)); _currentStmt->accept(this); - foreach (Move *load, _loads) + for (Move *load : _loads) newStatements.append(load); if (_currentStmt->asPhi()) newStatements.prepend(_currentStmt); else newStatements.append(_currentStmt); - foreach (Move *store, _stores) + for (Move *store : _stores) newStatements.append(store); } @@ -912,7 +912,7 @@ private: os << "Intervals live at the start of L" << bb->index() << ":" << endl; if (_liveAtStart[bb].isEmpty()) os << "\t(none)" << endl; - foreach (const LifeTimeInterval *i, _liveAtStart[bb]) { + for (const LifeTimeInterval *i : _liveAtStart.value(bb)) { os << "\t"; i->dump(os); os << endl; @@ -920,7 +920,7 @@ private: os << "Intervals live at the end of L" << bb->index() << ":" << endl; if (_liveAtEnd[bb].isEmpty()) os << "\t(none)" << endl; - foreach (const LifeTimeInterval *i, _liveAtEnd[bb]) { + for (const LifeTimeInterval *i : _liveAtEnd.value(bb)) { os << "\t"; i->dump(os); os << endl; @@ -943,7 +943,7 @@ private: Q_ASSERT(pReg); int spillSlot = _assignedSpillSlots[i->temp().index]; if (spillSlot != RegisterAllocator::InvalidSpillSlot) - _stores.append(generateSpill(spillSlot, i->temp().type, pReg->reg<int>())); + _stores.push_back(generateSpill(spillSlot, i->temp().type, pReg->reg<int>())); } void addNewIntervals(int position) @@ -976,15 +976,15 @@ private: void resolve() { - foreach (BasicBlock *bb, _function->basicBlocks()) { - foreach (BasicBlock *bbOut, bb->out) + for (BasicBlock *bb : _function->basicBlocks()) { + for (BasicBlock *bbOut : bb->out) resolveEdge(bb, bbOut); } } Phi *findDefPhi(const Temp &t, BasicBlock *bb) const { - foreach (Stmt *s, bb->statements()) { + for (Stmt *s : bb->statements()) { Phi *phi = s->asPhi(); if (!phi) return 0; @@ -1017,21 +1017,21 @@ private: int successorStart = _intervals->startPosition(successor); Q_ASSERT(successorStart > 0); - foreach (const LifeTimeInterval *it, _liveAtStart[successor]) { + for (const LifeTimeInterval *it : _liveAtStart.value(successor)) { bool isPhiTarget = false; Expr *moveFrom = 0; if (it->start() == successorStart) { if (Phi *phi = findDefPhi(it->temp(), successor)) { isPhiTarget = true; - Expr *opd = phi->d->incoming[successor->in.indexOf(predecessor)]; + Expr *opd = phi->incoming[successor->in.indexOf(predecessor)]; if (opd->asConst()) { moveFrom = opd; } else { Temp *t = opd->asTemp(); Q_ASSERT(t); - foreach (const LifeTimeInterval *it2, _liveAtEnd[predecessor]) { + for (const LifeTimeInterval *it2 : _liveAtEnd.value(predecessor)) { if (it2->temp() == *t && it2->reg() != LifeTimeInterval::InvalidRegister && it2->covers(predecessorEnd)) { @@ -1046,7 +1046,7 @@ private: } } } else { - foreach (const LifeTimeInterval *predIt, _liveAtEnd[predecessor]) { + for (const LifeTimeInterval *predIt : _liveAtEnd.value(predecessor)) { if (predIt->temp() == it->temp()) { if (predIt->reg() != LifeTimeInterval::InvalidRegister && predIt->covers(predecessorEnd)) { @@ -1191,7 +1191,7 @@ protected: Q_ASSERT(i->isSplitFromInterval()); const RegisterInfo *pReg = platformRegister(*i); Q_ASSERT(pReg); - _loads.append(generateUnspill(i->temp(), pReg->reg<int>())); + _loads.push_back(generateUnspill(i->temp(), pReg->reg<int>())); } if (i->reg() != LifeTimeInterval::InvalidRegister && @@ -1303,7 +1303,7 @@ void RegisterAllocator::run(IR::Function *function, const Optimizer &opt) qout << "Ranges:" << endl; QVector<LifeTimeInterval *> intervals = _unhandled; std::reverse(intervals.begin(), intervals.end()); - foreach (const LifeTimeInterval *r, intervals) { + for (const LifeTimeInterval *r : qAsConst(intervals)) { r->dump(qout); qout << endl; } @@ -1490,11 +1490,11 @@ void RegisterAllocator::linearScan() } } - foreach (LifeTimeInterval *r, _active) + for (LifeTimeInterval *r : qAsConst(_active)) if (!r->isFixedInterval()) _handled.append(r); _active.clear(); - foreach (LifeTimeInterval *r, _inactive) + for (LifeTimeInterval *r : qAsConst(_inactive)) if (!r->isFixedInterval()) _handled.append(r); _inactive.clear(); @@ -1922,7 +1922,7 @@ void RegisterAllocator::dump(IR::Function *function) const qout << "Ranges:" << endl; QVector<LifeTimeInterval *> handled = _handled; std::sort(handled.begin(), handled.end(), LifeTimeInterval::lessThanForTemp); - foreach (const LifeTimeInterval *r, handled) { + for (const LifeTimeInterval *r : qAsConst(handled)) { r->dump(qout); qout << endl; } diff --git a/src/qml/jsapi/qjsengine.h b/src/qml/jsapi/qjsengine.h index 300990873d..6ecd0c7ec0 100644 --- a/src/qml/jsapi/qjsengine.h +++ b/src/qml/jsapi/qjsengine.h @@ -111,7 +111,7 @@ private: friend inline bool qjsvalue_cast_helper(const QJSValue &, int, void *); protected: - QJSEngine(QJSEnginePrivate &dd, QObject *parent = 0); + QJSEngine(QJSEnginePrivate &dd, QObject *parent = Q_NULLPTR); private: QV8Engine *d; diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 317eb7a8a7..55ea1f91c3 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -576,15 +576,6 @@ ExecutionContext *ExecutionEngine::pushGlobalContext() return currentContext; } -ExecutionContext *ExecutionEngine::parentContext(ExecutionContext *context) const -{ - Value *offset = static_cast<Value *>(context) + 1; - Q_ASSERT(offset->isInteger()); - int o = offset->integerValue(); - return o ? context - o : 0; -} - - Heap::Object *ExecutionEngine::newObject() { return memoryManager->allocObject<Object>(); @@ -770,27 +761,6 @@ Heap::Object *ExecutionEngine::newForEachIteratorObject(Object *o) return obj->d(); } -Heap::QmlContext *ExecutionEngine::qmlContext() const -{ - Heap::ExecutionContext *ctx = current; - - // get the correct context when we're within a builtin function - if (ctx->type == Heap::ExecutionContext::Type_SimpleCallContext && !ctx->outer) - ctx = parentContext(currentContext)->d(); - - if (!ctx->outer) - return 0; - - while (ctx->outer && ctx->outer->type != Heap::ExecutionContext::Type_GlobalContext) - ctx = ctx->outer; - - Q_ASSERT(ctx); - if (ctx->type != Heap::ExecutionContext::Type_QmlContext) - return 0; - - return static_cast<Heap::QmlContext *>(ctx); -} - QObject *ExecutionEngine::qmlScopeObject() const { Heap::QmlContext *ctx = qmlContext(); diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 12ed98e6e7..7da4a1c3c1 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -500,6 +500,35 @@ inline void ExecutionEngine::popContext() current = currentContext->d(); } +inline ExecutionContext *ExecutionEngine::parentContext(ExecutionContext *context) const +{ + Value *offset = static_cast<Value *>(context) + 1; + Q_ASSERT(offset->isInteger()); + int o = offset->integerValue(); + return o ? context - o : 0; +} + +inline Heap::QmlContext *ExecutionEngine::qmlContext() const +{ + Heap::ExecutionContext *ctx = current; + + // get the correct context when we're within a builtin function + if (ctx->type == Heap::ExecutionContext::Type_SimpleCallContext && !ctx->outer) + ctx = parentContext(currentContext)->d(); + + if (!ctx->outer) + return 0; + + while (ctx->outer && ctx->outer->type != Heap::ExecutionContext::Type_GlobalContext) + ctx = ctx->outer; + + Q_ASSERT(ctx); + if (ctx->type != Heap::ExecutionContext::Type_QmlContext) + return 0; + + return static_cast<Heap::QmlContext *>(ctx); +} + inline void Heap::Base::mark(QV4::ExecutionEngine *engine) { diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index dd86c50270..470791fb00 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -141,8 +141,8 @@ struct ReadAccessor { { Q_ASSERT(property.accessors); - property.accessors->read(object, property.accessorData, output); - if (n) property.accessors->notifier(object, property.accessorData, n); + property.accessors->read(object, output); + if (n) property.accessors->notifier(object, n); } }; diff --git a/src/qml/jsruntime/qv4util_p.h b/src/qml/jsruntime/qv4util_p.h index 3ffcc8a846..59c12c5e46 100644 --- a/src/qml/jsruntime/qv4util_p.h +++ b/src/qml/jsruntime/qv4util_p.h @@ -51,6 +51,9 @@ // #include "qv4global_p.h" +#include <QtCore/QBitArray> +#include <algorithm> +#include <vector> QT_BEGIN_NAMESPACE @@ -76,6 +79,130 @@ private: TemporaryAssignment operator=(const TemporaryAssignment<T>&); }; +#if !defined(BROKEN_STD_VECTOR_BOOL_OR_BROKEN_STD_FIND) +// Sanity: +class BitVector +{ + std::vector<bool> bits; + +public: + BitVector(int size = 0, bool value = false) + : bits(size, value) + {} + + void reserve(int size) + { bits.reserve(size); } + + int size() const + { + Q_ASSERT(bits.size() < INT_MAX); + return static_cast<int>(bits.size()); + } + + void resize(int newSize) + { bits.resize(newSize); } + + void resize(int newSize, bool newValue) + { bits.resize(newSize, newValue); } + + void assign(int newSize, bool value) + { bits.assign(newSize, value); } + + int findNext(int start, bool value, bool wrapAround) const + { + // The ++operator of std::vector<bool>::iterator in libc++ has a bug when using it on an + // iterator pointing to the last element. It will not be set to ::end(), but beyond + // that. (It will be set to the first multiple of the native word size that is bigger + // than size().) + // + // See http://llvm.org/bugs/show_bug.cgi?id=19663 + // + // The work-around is to calculate the distance, and compare it to the size() to see if it's + // beyond the end, or take the minimum of the distance and the size. + + size_t pos = std::distance(bits.begin(), + std::find(bits.begin() + start, bits.end(), value)); + if (wrapAround && pos >= static_cast<size_t>(size())) + pos = std::distance(bits.begin(), + std::find(bits.begin(), bits.begin() + start, value)); + + pos = qMin(pos, static_cast<size_t>(size())); + + Q_ASSERT(pos <= static_cast<size_t>(size())); + Q_ASSERT(pos < INT_MAX); + + return static_cast<int>(pos); + } + + bool at(int idx) const + { return bits.at(idx); } + + void setBit(int idx) + { bits[idx] = true; } + + void clearBit(int idx) + { bits[idx] = false; } +}; +#else // Insanity: +class BitVector +{ + QBitArray bits; + +public: + BitVector(int size = 0, bool value = false) + : bits(size, value) + {} + + void reserve(int size) + { Q_UNUSED(size); } + + int size() const + { return bits.size(); } + + void resize(int newSize) + { bits.resize(newSize); } + + void resize(int newSize, bool newValue) + { + int oldSize = bits.size(); + bits.resize(newSize); + bits.fill(newValue, oldSize, bits.size()); + } + + void assign(int newSize, bool value) + { + bits.resize(newSize); + bits.fill(value); + } + + int findNext(int start, bool value, bool wrapAround) const + { + for (int i = start, ei = size(); i < ei; ++i) { + if (at(i) == value) + return i; + } + + if (wrapAround) { + for (int i = 0, ei = start; i < ei; ++i) { + if (at(i) == value) + return i; + } + } + + return size(); + } + + bool at(int idx) const + { return bits.at(idx); } + + void setBit(int idx) + { bits[idx] = true; } + + void clearBit(int idx) + { bits[idx] = false; } +}; +#endif + } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index e8320b33d2..514bdafb48 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -119,11 +119,14 @@ struct Q_QML_PRIVATE_EXPORT Value Q_ALWAYS_INLINE quint32 value() const { return _val >> 32; } #endif -#ifdef QV4_USE_64_BIT_VALUE_ENCODING +#if defined(V4_BOOTSTRAP) + Q_ALWAYS_INLINE Heap::Base *m() const { Q_UNREACHABLE(); return Q_NULLPTR; } + Q_ALWAYS_INLINE void setM(Heap::Base *b) { Q_UNUSED(b); Q_UNREACHABLE(); } +#elif defined(QV4_USE_64_BIT_VALUE_ENCODING) Q_ALWAYS_INLINE Heap::Base *m() const { Heap::Base *b; memcpy(&b, &_val, 8); return b; } Q_ALWAYS_INLINE void setM(Heap::Base *b) { memcpy(&_val, &b, 8); } #else // !QV4_USE_64_BIT_VALUE_ENCODING - Q_ALWAYS_INLINE Heap::Base *m() const { Heap::Base *b; quint32 v = value(); memcpy(&b, &v, 4); return b; } + Q_ALWAYS_INLINE Heap::Base *m() const { Q_STATIC_ASSERT(sizeof(Heap::Base*) == sizeof(quint32)); Heap::Base *b; quint32 v = value(); memcpy(&b, &v, 4); return b; } Q_ALWAYS_INLINE void setM(Heap::Base *b) { quint32 v; memcpy(&v, &b, 4); setValue(v); } #endif diff --git a/src/qml/parser/qqmljsmemorypool_p.h b/src/qml/parser/qqmljsmemorypool_p.h index 3659271bc6..08609e2961 100644 --- a/src/qml/parser/qqmljsmemorypool_p.h +++ b/src/qml/parser/qqmljsmemorypool_p.h @@ -94,7 +94,7 @@ public: inline void *allocate(size_t size) { size = (size + 7) & ~7; - if (_ptr && (_ptr + size < _end)) { + if (Q_LIKELY(_ptr && (_ptr + size < _end))) { void *addr = _ptr; _ptr += size; return addr; @@ -111,7 +111,7 @@ public: template <typename Tp> Tp *New() { return new (this->allocate(sizeof(Tp))) Tp(); } private: - void *allocate_helper(size_t size) + Q_NEVER_INLINE void *allocate_helper(size_t size) { Q_ASSERT(size < BLOCK_SIZE); diff --git a/src/qml/qml/ftw/qhashedstring_p.h b/src/qml/qml/ftw/qhashedstring_p.h index 4ddac0c2c6..6ff3e4a11b 100644 --- a/src/qml/qml/ftw/qhashedstring_p.h +++ b/src/qml/qml/ftw/qhashedstring_p.h @@ -54,7 +54,6 @@ #include <QtCore/qglobal.h> #include <QtCore/qstring.h> #include <private/qv4string_p.h> -#include <private/qv4scopedvalue_p.h> #include <private/qflagpointer_p.h> diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index a71d06f7de..8fb710ad9d 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -111,10 +111,11 @@ int qmlRegisterType() qRegisterNormalizedMetaType<T *>(pointerName.constData()), qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), - 0, 0, + 0, + Q_NULLPTR, QString(), - 0, 0, 0, 0, &T::staticMetaObject, + Q_NULLPTR, 0, 0, Q_NULLPTR, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -123,9 +124,9 @@ int qmlRegisterType() QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(), QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(), - 0, 0, + Q_NULLPTR, Q_NULLPTR, - 0, + Q_NULLPTR, 0 }; @@ -144,7 +145,8 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin qRegisterNormalizedMetaType<T *>(pointerName.constData()), qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), - 0, 0, + 0, + Q_NULLPTR, reason, uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, @@ -156,9 +158,9 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(), QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(), - 0, 0, + Q_NULLPTR, Q_NULLPTR, - 0, + Q_NULLPTR, 0 }; @@ -175,7 +177,8 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin qRegisterNormalizedMetaType<T *>(pointerName.constData()), qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), - 0, 0, + 0, + Q_NULLPTR, reason, uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, @@ -187,9 +190,9 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(), QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(), - 0, 0, + Q_NULLPTR, Q_NULLPTR, - 0, + Q_NULLPTR, metaObjectRevision }; @@ -213,7 +216,8 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve qRegisterNormalizedMetaType<T *>(pointerName.constData()), qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), - 0, 0, + 0, + Q_NULLPTR, reason, uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, @@ -227,7 +231,7 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve QQmlPrivate::createParent<E>, &E::staticMetaObject, - 0, + Q_NULLPTR, 0 }; @@ -256,9 +260,9 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(), QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(), - 0, 0, + Q_NULLPTR, Q_NULLPTR, - 0, + Q_NULLPTR, 0 }; @@ -287,9 +291,9 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(), QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(), - 0, 0, + Q_NULLPTR, Q_NULLPTR, - 0, + Q_NULLPTR, metaObjectRevision }; @@ -318,9 +322,9 @@ int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor) QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(), QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(), - 0, 0, + Q_NULLPTR, Q_NULLPTR, - 0, + Q_NULLPTR, metaObjectRevision }; @@ -338,10 +342,11 @@ int qmlRegisterExtendedType() qRegisterNormalizedMetaType<T *>(pointerName.constData()), qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), - 0, 0, + 0, + Q_NULLPTR, QString(), - 0, 0, 0, 0, &T::staticMetaObject, + Q_NULLPTR, 0, 0, Q_NULLPTR, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -352,7 +357,7 @@ int qmlRegisterExtendedType() QQmlPrivate::createParent<E>, &E::staticMetaObject, - 0, + Q_NULLPTR, 0 }; @@ -391,7 +396,7 @@ int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, QQmlPrivate::createParent<E>, &E::staticMetaObject, - 0, + Q_NULLPTR, 0 }; @@ -441,7 +446,7 @@ int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor, QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(), QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(), - 0, 0, + Q_NULLPTR, Q_NULLPTR, parser, 0 @@ -536,7 +541,7 @@ inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versi uri, versionMajor, versionMinor, typeName, - callback, 0, 0, 0, 0 + callback, Q_NULLPTR, Q_NULLPTR, 0, 0 }; return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api); @@ -554,7 +559,7 @@ inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versi uri, versionMajor, versionMinor, typeName, - 0, callback, &T::staticMetaObject, qRegisterNormalizedMetaType<T *>(pointerName.constData()), 0 + Q_NULLPTR, callback, &T::staticMetaObject, qRegisterNormalizedMetaType<T *>(pointerName.constData()), 0 }; return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api); diff --git a/src/qml/qml/qqmlaccessors_p.h b/src/qml/qml/qqmlaccessors_p.h index cae4e2c2ff..55562a5307 100644 --- a/src/qml/qml/qqmlaccessors_p.h +++ b/src/qml/qml/qqmlaccessors_p.h @@ -103,7 +103,7 @@ class QQmlNotifier; } while (false); #define QML_PRIVATE_ACCESSOR(clazz, cpptype, name, variable) \ - static void clazz ## _ ## name ## Read(QObject *o, qintptr, void *rv) \ + static void clazz ## _ ## name ## Read(QObject *o, void *rv) \ { \ clazz ## Private *d = clazz ## Private::get(static_cast<clazz *>(o)); \ *static_cast<cpptype *>(rv) = d->variable; \ @@ -114,8 +114,8 @@ class QQmlNotifier; class QQmlAccessors { public: - void (*read)(QObject *object, qintptr property, void *output); - void (*notifier)(QObject *object, qintptr property, QQmlNotifier **notifier); + void (*read)(QObject *object, void *output); + void (*notifier)(QObject *object, QQmlNotifier **notifier); }; namespace QQmlAccessorProperties { diff --git a/src/qml/qml/qqmlapplicationengine.h b/src/qml/qml/qqmlapplicationengine.h index 59667a1841..ff7dce5f8b 100644 --- a/src/qml/qml/qqmlapplicationengine.h +++ b/src/qml/qml/qqmlapplicationengine.h @@ -53,9 +53,9 @@ class Q_QML_EXPORT QQmlApplicationEngine : public QQmlEngine { Q_OBJECT public: - QQmlApplicationEngine(QObject *parent=0); - QQmlApplicationEngine(const QUrl &url, QObject *parent=0); - QQmlApplicationEngine(const QString &filePath, QObject *parent=0); + QQmlApplicationEngine(QObject *parent = Q_NULLPTR); + QQmlApplicationEngine(const QUrl &url, QObject *parent = Q_NULLPTR); + QQmlApplicationEngine(const QString &filePath, QObject *parent = Q_NULLPTR); ~QQmlApplicationEngine(); QList<QObject*> rootObjects(); diff --git a/src/qml/qml/qqmlcomponent.h b/src/qml/qml/qqmlcomponent.h index 0e226320d6..aefbf20aff 100644 --- a/src/qml/qml/qqmlcomponent.h +++ b/src/qml/qml/qqmlcomponent.h @@ -72,12 +72,12 @@ public: enum CompilationMode { PreferSynchronous, Asynchronous }; Q_ENUM(CompilationMode) - QQmlComponent(QObject *parent = 0); - QQmlComponent(QQmlEngine *, QObject *parent=0); - QQmlComponent(QQmlEngine *, const QString &fileName, QObject *parent = 0); - QQmlComponent(QQmlEngine *, const QString &fileName, CompilationMode mode, QObject *parent = 0); - QQmlComponent(QQmlEngine *, const QUrl &url, QObject *parent = 0); - QQmlComponent(QQmlEngine *, const QUrl &url, CompilationMode mode, QObject *parent = 0); + QQmlComponent(QObject *parent = Q_NULLPTR); + QQmlComponent(QQmlEngine *, QObject *parent = Q_NULLPTR); + QQmlComponent(QQmlEngine *, const QString &fileName, QObject *parent = Q_NULLPTR); + QQmlComponent(QQmlEngine *, const QString &fileName, CompilationMode mode, QObject *parent = Q_NULLPTR); + QQmlComponent(QQmlEngine *, const QUrl &url, QObject *parent = Q_NULLPTR); + QQmlComponent(QQmlEngine *, const QUrl &url, CompilationMode mode, QObject *parent = Q_NULLPTR); virtual ~QQmlComponent(); enum Status { Null, Ready, Loading, Error }; @@ -96,12 +96,12 @@ public: QUrl url() const; - virtual QObject *create(QQmlContext *context = 0); + virtual QObject *create(QQmlContext *context = Q_NULLPTR); virtual QObject *beginCreate(QQmlContext *); virtual void completeCreate(); - void create(QQmlIncubator &, QQmlContext *context = 0, - QQmlContext *forContext = 0); + void create(QQmlIncubator &, QQmlContext *context = Q_NULLPTR, + QQmlContext *forContext = Q_NULLPTR); QQmlContext *creationContext() const; diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index f759f46af5..65a337f4e5 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -95,7 +95,7 @@ QQmlContextPrivate::QQmlContextPrivate() by name in the context, as though they were all individually added through calls to QQmlContext::setContextProperty(). Changes to the property's values are detected through the property's notify signal. Setting a context object is both - faster and easier than manually adding and maintaing context property values. + faster and easier than manually adding and maintaining context property values. The following example has the same effect as the previous one, but it uses a context object. diff --git a/src/qml/qml/qqmlcontext.h b/src/qml/qml/qqmlcontext.h index c6b5d44f5a..781eac44fc 100644 --- a/src/qml/qml/qqmlcontext.h +++ b/src/qml/qml/qqmlcontext.h @@ -62,8 +62,8 @@ class Q_QML_EXPORT QQmlContext : public QObject Q_DECLARE_PRIVATE(QQmlContext) public: - QQmlContext(QQmlEngine *parent, QObject *objParent=0); - QQmlContext(QQmlContext *parent, QObject *objParent=0); + QQmlContext(QQmlEngine *parent, QObject *objParent = Q_NULLPTR); + QQmlContext(QQmlContext *parent, QObject *objParent = Q_NULLPTR); virtual ~QQmlContext(); bool isValid() const; diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h index 057f4b54c0..48d596418d 100644 --- a/src/qml/qml/qqmlcontext_p.h +++ b/src/qml/qml/qqmlcontext_p.h @@ -66,6 +66,7 @@ #include <private/qflagpointer_p.h> #include <private/qqmlguard_p.h> +#include <private/qv4compileddata_p.h> #include <private/qv4identifier_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h index 28bd66047e..132af78f80 100644 --- a/src/qml/qml/qqmlengine.h +++ b/src/qml/qml/qqmlengine.h @@ -97,7 +97,7 @@ class Q_QML_EXPORT QQmlEngine : public QJSEngine Q_PROPERTY(QString offlineStoragePath READ offlineStoragePath WRITE setOfflineStoragePath) Q_OBJECT public: - QQmlEngine(QObject *p = 0); + explicit QQmlEngine(QObject *p = Q_NULLPTR); virtual ~QQmlEngine(); QQmlContext *rootContext() const; diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h index 7258ffe6ed..795a505742 100644 --- a/src/qml/qml/qqmlengine_p.h +++ b/src/qml/qml/qqmlengine_p.h @@ -375,7 +375,7 @@ const QQmlEnginePrivate *QQmlEnginePrivate::get(const QQmlEngine *e) { Q_ASSERT(e); - return e->d_func(); + return e ? e->d_func() : nullptr; } QQmlEnginePrivate *QQmlEnginePrivate::get(QQmlContext *c) diff --git a/src/qml/qml/qqmlexpression.h b/src/qml/qml/qqmlexpression.h index 0aff4884f9..5239d59c8a 100644 --- a/src/qml/qml/qqmlexpression.h +++ b/src/qml/qml/qqmlexpression.h @@ -60,8 +60,8 @@ class Q_QML_EXPORT QQmlExpression : public QObject Q_OBJECT public: QQmlExpression(); - QQmlExpression(QQmlContext *, QObject *, const QString &, QObject * = 0); - explicit QQmlExpression(const QQmlScriptString &, QQmlContext * = 0, QObject * = 0, QObject * = 0); + QQmlExpression(QQmlContext *, QObject *, const QString &, QObject * = Q_NULLPTR); + explicit QQmlExpression(const QQmlScriptString &, QQmlContext * = Q_NULLPTR, QObject * = Q_NULLPTR, QObject * = Q_NULLPTR); virtual ~QQmlExpression(); QQmlEngine *engine() const; @@ -84,7 +84,7 @@ public: void clearError(); QQmlError error() const; - QVariant evaluate(bool *valueIsUndefined = 0); + QVariant evaluate(bool *valueIsUndefined = Q_NULLPTR); Q_SIGNALS: void valueChanged(); diff --git a/src/qml/qml/qqmlextensionplugin.h b/src/qml/qml/qqmlextensionplugin.h index d0ee16ac50..de482d0352 100644 --- a/src/qml/qml/qqmlextensionplugin.h +++ b/src/qml/qml/qqmlextensionplugin.h @@ -58,7 +58,7 @@ class Q_QML_EXPORT QQmlExtensionPlugin Q_INTERFACES(QQmlExtensionInterface) Q_INTERFACES(QQmlTypesExtensionInterface) public: - explicit QQmlExtensionPlugin(QObject *parent = 0); + explicit QQmlExtensionPlugin(QObject *parent = Q_NULLPTR); ~QQmlExtensionPlugin(); QUrl baseUrl() const; diff --git a/src/qml/qml/qqmlfileselector.h b/src/qml/qml/qqmlfileselector.h index 34ba4d7a56..03b951420e 100644 --- a/src/qml/qml/qqmlfileselector.h +++ b/src/qml/qml/qqmlfileselector.h @@ -54,7 +54,7 @@ class Q_QML_EXPORT QQmlFileSelector : public QObject Q_OBJECT Q_DECLARE_PRIVATE(QQmlFileSelector) public: - QQmlFileSelector(QQmlEngine* engine, QObject* parent=0); + explicit QQmlFileSelector(QQmlEngine *engine, QObject *parent = Q_NULLPTR); ~QQmlFileSelector(); QFileSelector *selector() const Q_DECL_NOTHROW; void setSelector(QFileSelector *selector); diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 0014ccd3ba..d6c81bcc49 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -888,6 +888,11 @@ bool QQmlImportsPrivate::populatePluginPairVector(QVector<StaticPluginPair> &res } #endif +static inline QString msgCannotLoadPlugin(const QString &uri, const QString &why) +{ + return QQmlImportDatabase::tr("plugin cannot be loaded for module \"%1\": %2").arg(uri, why); +} + /*! Import an extension defined by a qmldir file. @@ -949,7 +954,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath, // The reason is that the lower level may add url and line/column numbering information. QQmlError poppedError = errors->takeFirst(); QQmlError error; - error.setDescription(QQmlImportDatabase::tr("plugin cannot be loaded for module \"%1\": %2").arg(uri).arg(poppedError.description())); + error.setDescription(msgCannotLoadPlugin(uri, poppedError.description())); error.setUrl(QUrl::fromLocalFile(qmldirFilePath)); errors->prepend(error); } @@ -1020,10 +1025,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath, if (errors) { QQmlError error; - error.setDescription( - QQmlImportDatabase::tr( - "plugin cannot be loaded for module \"%1\": library loading is disabled") - .arg(uri)); + error.setDescription(msgCannotLoadPlugin(uri, QQmlImportDatabase::tr("library loading is disabled"))); error.setUrl(QUrl::fromLocalFile(qmldirFilePath)); errors->prepend(error); } diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp index aef0916239..15d0a571a5 100644 --- a/src/qml/qml/qqmljavascriptexpression.cpp +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -298,7 +298,7 @@ void QQmlPropertyCapture::registerQmlDependencies(QV4::ExecutionEngine *engine, // Let the caller check and avoid the function call :) Q_ASSERT(compiledFunction->hasQmlDependencies()); - QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0; + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine->qmlEngine()); if (!ep) return; QQmlPropertyCapture *capture = ep->propertyCapture; diff --git a/src/qml/qml/qqmllist.h b/src/qml/qml/qqmllist.h index dd548168c3..e3955deee5 100644 --- a/src/qml/qml/qqmllist.h +++ b/src/qml/qml/qqmllist.h @@ -61,15 +61,41 @@ public: typedef void (*ClearFunction)(QQmlListProperty<T> *); QQmlListProperty() - : object(0), data(0), append(0), count(0), at(0), clear(0), dummy1(0), dummy2(0) {} + : object(Q_NULLPTR), + data(Q_NULLPTR), + append(Q_NULLPTR), + count(Q_NULLPTR), + at(Q_NULLPTR), + clear(Q_NULLPTR), + dummy1(Q_NULLPTR), + dummy2(Q_NULLPTR) + {} QQmlListProperty(QObject *o, QList<T *> &list) : object(o), data(&list), append(qlist_append), count(qlist_count), at(qlist_at), - clear(qlist_clear), dummy1(0), dummy2(0) {} + clear(qlist_clear), + dummy1(Q_NULLPTR), + dummy2(Q_NULLPTR) + {} QQmlListProperty(QObject *o, void *d, AppendFunction a, CountFunction c, AtFunction t, ClearFunction r ) - : object(o), data(d), append(a), count(c), at(t), clear(r), dummy1(0), dummy2(0) {} + : object(o), + data(d), + append(a), + count(c), + at(t), + clear(r), + dummy1(Q_NULLPTR), + dummy2(Q_NULLPTR) + {} QQmlListProperty(QObject *o, void *d, CountFunction c, AtFunction t) - : object(o), data(d), append(0), count(c), at(t), clear(0), dummy1(0), dummy2(0) {} + : object(o), + data(d), + append(Q_NULLPTR), + count(c), at(t), + clear(Q_NULLPTR), + dummy1(Q_NULLPTR), + dummy2(Q_NULLPTR) + {} bool operator==(const QQmlListProperty &o) const { return object == o.object && data == o.data && @@ -114,7 +140,7 @@ class Q_QML_EXPORT QQmlListReference { public: QQmlListReference(); - QQmlListReference(QObject *, const char *property, QQmlEngine * = 0); + QQmlListReference(QObject *, const char *property, QQmlEngine * = Q_NULLPTR); QQmlListReference(const QQmlListReference &); QQmlListReference &operator=(const QQmlListReference &); ~QQmlListReference(); diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 1a7896bde8..29fff04325 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -716,6 +716,8 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con QQmlTypeNameCache::Result res = context->imports->query(stringAt(binding->propertyNameIndex)); if (res.isValid()) attachedType = res.type; + else + return false; } const int id = attachedType->attachedPropertiesId(QQmlEnginePrivate::get(engine)); QObject *qmlObject = qmlAttachedPropertiesObjectById(id, _qobject); diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index 357b5ae577..3be52cf461 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -698,7 +698,6 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject, if (accessorProperty) { data->flags |= QQmlPropertyData::HasAccessors; data->accessors = accessorProperty->accessors; - data->accessorData = accessorProperty->data; } else if (old) { data->markAsOverrideOf(old); } diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index 0b3573c58c..4ff5ee89f9 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -209,7 +209,6 @@ public: }; struct { // When HasAccessors QQmlAccessors *accessors; - qintptr accessorData; }; }; int coreIndex; diff --git a/src/qml/types/qqmllistmodelworkeragent_p.h b/src/qml/types/qqmllistmodelworkeragent_p.h index 0c639b140d..f9872a6ad4 100644 --- a/src/qml/types/qqmllistmodelworkeragent_p.h +++ b/src/qml/types/qqmllistmodelworkeragent_p.h @@ -97,7 +97,8 @@ public: VariantRef &operator=(const VariantRef &o) { if (o.a) o.a->addref(); - if (a) a->release(); a = o.a; + if (a) a->release(); + a = o.a; return *this; } diff --git a/src/qml/util/qqmlpropertymap.h b/src/qml/util/qqmlpropertymap.h index ea1561bc60..01048f3662 100644 --- a/src/qml/util/qqmlpropertymap.h +++ b/src/qml/util/qqmlpropertymap.h @@ -55,7 +55,7 @@ class Q_QML_EXPORT QQmlPropertyMap : public QObject { Q_OBJECT public: - explicit QQmlPropertyMap(QObject *parent = 0); + explicit QQmlPropertyMap(QObject *parent = Q_NULLPTR); virtual ~QQmlPropertyMap(); QVariant value(const QString &key) const; |