diff options
author | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-01-06 16:12:40 +0100 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-01-06 16:12:41 +0100 |
commit | 24e2b39e7a06687322a18a158a083eb51a7c0dca (patch) | |
tree | 1a32caf6dd6db74fbac9553a094bb00b216fa678 /src/qml/compiler | |
parent | 39540124dd0900e0c99dcda8c0ebdf4f3cea8d5e (diff) | |
parent | daff5f2988cef31442629a48c3b3088abf01837a (diff) |
Merge remote-tracking branch 'origin/stable' into dev
Change-Id: If9a205bea219b9aca95d78b1e556ca9bbff58dd0
Diffstat (limited to 'src/qml/compiler')
-rw-r--r-- | src/qml/compiler/qqmlcodegenerator.cpp | 67 | ||||
-rw-r--r-- | src/qml/compiler/qv4ssa.cpp | 300 |
2 files changed, 210 insertions, 157 deletions
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp index 8809221abe..13b23fde68 100644 --- a/src/qml/compiler/qqmlcodegenerator.cpp +++ b/src/qml/compiler/qqmlcodegenerator.cpp @@ -1347,38 +1347,29 @@ static V4IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, V4IR::MemberExpre V4IR::Type result = V4IR::VarType; QQmlType *type = static_cast<QQmlType*>(resolver->data); - if (type->isSingleton()) { - if (type->isCompositeSingleton()) { - QQmlTypeData *tdata = qmlEngine->typeLoader.getType(type->singletonInstanceInfo()->url); - Q_ASSERT(tdata); - Q_ASSERT(tdata->isComplete()); - initMetaObjectResolver(resolver, qmlEngine->propertyCacheForType(tdata->compiledData()->metaTypeId)); - resolver->flags |= AllPropertiesAreFinal; - } else { - const QMetaObject *singletonMo = type->singletonInstanceInfo()->instanceMetaObject; - if (!singletonMo) { // We can only accelerate C++ singletons that were registered with their meta-type - resolver->clear(); - return result; - } - initMetaObjectResolver(resolver, qmlEngine->cache(singletonMo)); - resolver->flags |= LookupsIncludeEnums; + + if (member->name->constData()->isUpper()) { + bool ok = false; + int value = type->enumValue(*member->name, &ok); + if (ok) { + member->setEnumValue(value); + resolver->clear(); + return V4IR::SInt32Type; } + } + + if (type->isCompositeSingleton()) { + QQmlTypeData *tdata = qmlEngine->typeLoader.getType(type->singletonInstanceInfo()->url); + Q_ASSERT(tdata); + Q_ASSERT(tdata->isComplete()); + initMetaObjectResolver(resolver, qmlEngine->propertyCacheForType(tdata->compiledData()->metaTypeId)); + resolver->flags |= AllPropertiesAreFinal; + return resolver->resolveMember(qmlEngine, resolver, member); + } else if (const QMetaObject *attachedMeta = type->attachedPropertiesType()) { + QQmlPropertyCache *cache = qmlEngine->cache(attachedMeta); + initMetaObjectResolver(resolver, cache); + member->setAttachedPropertiesId(type->attachedPropertiesId()); return resolver->resolveMember(qmlEngine, resolver, member); - } else { - if (member->name->constData()->isUpper()) { - bool ok = false; - int value = type->enumValue(*member->name, &ok); - if (ok) { - member->setEnumValue(value); - resolver->clear(); - return V4IR::SInt32Type; - } - } else if (const QMetaObject *attachedMeta = type->attachedPropertiesType()) { - QQmlPropertyCache *cache = qmlEngine->cache(attachedMeta); - initMetaObjectResolver(resolver, cache); - member->setAttachedPropertiesId(type->attachedPropertiesId()); - return resolver->resolveMember(qmlEngine, resolver, member); - } } resolver->clear(); @@ -1559,8 +1550,10 @@ V4IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int col V4IR::Temp *result = _block->TEMP(_block->newTemp()); _block->MOVE(result, s); result = _block->TEMP(result->index); - initMetaObjectResolver(&result->memberResolver, mapping.type); - result->memberResolver.flags |= AllPropertiesAreFinal; + if (mapping.type) { + initMetaObjectResolver(&result->memberResolver, mapping.type); + result->memberResolver.flags |= AllPropertiesAreFinal; + } result->isReadOnly = true; // don't allow use as lvalue return result; } @@ -1573,14 +1566,14 @@ V4IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int col } else if (r.type) { V4IR::Name *typeName = _block->NAME(name, line, col); // Make sure the run-time loads this through the more efficient singleton getter. - typeName->qmlSingleton = r.type->isSingleton(); + typeName->qmlSingleton = r.type->isCompositeSingleton(); typeName->freeOfSideEffects = true; - V4IR::Temp *result = _block->TEMP(_block->newTemp()); - initQmlTypeResolver(&result->memberResolver, r.type); - _block->MOVE(result, typeName); - return _block->TEMP(result->index); + + result = _block->TEMP(result->index); + initQmlTypeResolver(&result->memberResolver, r.type); + return result; } else { Q_ASSERT(r.importNamespace); V4IR::Name *namespaceName = _block->NAME(name, line, col); diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp index eccdfff623..679cf1b3a7 100644 --- a/src/qml/compiler/qv4ssa.cpp +++ b/src/qml/compiler/qv4ssa.cpp @@ -39,6 +39,10 @@ ** ****************************************************************************/ +#ifndef QT_NO_DEBUG +# define _LIBCPP_DEBUG2 0 +#endif // QT_NO_DEBUG + #include "qv4ssa_p.h" #include "qv4isel_util_p.h" #include "qv4util_p.h" @@ -256,71 +260,88 @@ inline Temp *unescapableTemp(Expr *e, bool variablesCanEscape) } class DominatorTree { + typedef int BasicBlockIndex; + enum { InvalidBasicBlockIndex = -1 }; + + const QVector<BasicBlock *> nodes; int N; - QHash<BasicBlock *, int> dfnum; - QVector<BasicBlock *> vertex; - QHash<BasicBlock *, BasicBlock *> parent; - QHash<BasicBlock *, BasicBlock *> ancestor; - QHash<BasicBlock *, BasicBlock *> best; - QHash<BasicBlock *, BasicBlock *> semi; - QHash<BasicBlock *, BasicBlock *> idom; - QHash<BasicBlock *, BasicBlock *> samedom; - QHash<BasicBlock *, QSet<BasicBlock *> > bucket; + std::vector<int> dfnum; // BasicBlock index -> dfnum + std::vector<int> vertex; + std::vector<BasicBlockIndex> parent; // BasicBlock index -> parent BasicBlock index + std::vector<BasicBlockIndex> ancestor; // BasicBlock index -> ancestor BasicBlock index + std::vector<BasicBlockIndex> best; // BasicBlock index -> best BasicBlock index + std::vector<BasicBlockIndex> semi; // BasicBlock index -> semi dominator BasicBlock index + std::vector<BasicBlockIndex> idom; // BasicBlock index -> immediate dominator BasicBlock index + std::vector<BasicBlockIndex> samedom; // BasicBlock index -> same dominator BasicBlock index + std::vector<QSet<BasicBlock *> > DF; // BasicBlock index -> dominator frontier struct DFSTodo { - BasicBlock *node, *parent; + BasicBlockIndex node, parent; + + DFSTodo() + : node(InvalidBasicBlockIndex) + , parent(InvalidBasicBlockIndex) + {} - DFSTodo():node(0),parent(0){} - DFSTodo(BasicBlock *node, BasicBlock *parent):node(node),parent(parent){} + DFSTodo(BasicBlockIndex node, BasicBlockIndex parent) + : node(node) + , parent(parent) + {} }; - void DFS(BasicBlock *node) { - QVector<DFSTodo> worklist; - worklist.reserve(vertex.capacity()); - DFSTodo todo(node, 0); + void DFS(BasicBlockIndex node) { + std::vector<DFSTodo> worklist; + worklist.reserve(vertex.capacity() / 2); + DFSTodo todo(node, InvalidBasicBlockIndex); while (true) { - BasicBlock *n = todo.node; + BasicBlockIndex n = todo.node; if (dfnum[n] == 0) { dfnum[n] = N; vertex[N] = n; parent[n] = todo.parent; ++N; - for (int i = n->out.size() - 1; i > 0; --i) - worklist.append(DFSTodo(n->out[i], n)); + const QVector<BasicBlock *> &out = nodes[n]->out; + for (int i = out.size() - 1; i > 0; --i) + worklist.push_back(DFSTodo(out[i]->index, n)); - if (n->out.size() > 0) { - todo.node = n->out.first(); + if (out.size() > 0) { + todo.node = out.first()->index; todo.parent = n; continue; } } - if (worklist.isEmpty()) + if (worklist.empty()) break; - todo = worklist.last(); - worklist.removeLast(); + todo = worklist.back(); + worklist.pop_back(); } + +#if defined(SHOW_SSA) + for (int i = 0; i < nodes.size(); ++i) + qDebug("\tL%d: dfnum = %d, parent = %d", i, dfnum[i], parent[i]); +#endif // SHOW_SSA } - BasicBlock *ancestorWithLowestSemi(BasicBlock *v) { - QVector<BasicBlock *> worklist; - worklist.reserve(vertex.capacity()); - for (BasicBlock *it = v; it; it = ancestor[it]) - worklist.append(it); + BasicBlockIndex ancestorWithLowestSemi(BasicBlockIndex v) { + std::vector<BasicBlockIndex> worklist; + worklist.reserve(vertex.capacity() / 2); + for (BasicBlockIndex it = v; it != InvalidBasicBlockIndex; it = ancestor[it]) + worklist.push_back(it); if (worklist.size() < 2) return best[v]; - BasicBlock *b = 0; - BasicBlock *last = worklist.last(); + BasicBlockIndex b = InvalidBasicBlockIndex; + BasicBlockIndex last = worklist.back(); for (int it = worklist.size() - 2; it >= 0; --it) { - BasicBlock *bbIt = worklist[it]; + BasicBlockIndex bbIt = worklist[it]; ancestor[bbIt] = last; - BasicBlock *&best_it = best[bbIt]; - if (b && dfnum[semi[b]] < dfnum[semi[best_it]]) + BasicBlockIndex &best_it = best[bbIt]; + if (b != InvalidBasicBlockIndex && dfnum[semi[b]] < dfnum[semi[best_it]]) best_it = b; else b = best_it; @@ -328,66 +349,82 @@ class DominatorTree { return b; } - void link(BasicBlock *p, BasicBlock *n) { + void link(BasicBlockIndex p, BasicBlockIndex n) { ancestor[n] = p; best[n] = n; } - void calculateIDoms(const QVector<BasicBlock *> &nodes) { + void calculateIDoms() { Q_ASSERT(nodes.first()->in.isEmpty()); - vertex.resize(nodes.size()); - foreach (BasicBlock *n, nodes) { - dfnum[n] = 0; - semi[n] = 0; - ancestor[n] = 0; - idom[n] = 0; - samedom[n] = 0; - } - DFS(nodes.first()); + vertex = std::vector<int>(nodes.size(), InvalidBasicBlockIndex); + parent = std::vector<int>(nodes.size(), InvalidBasicBlockIndex); + dfnum = std::vector<int>(nodes.size(), 0); + semi = std::vector<BasicBlockIndex>(nodes.size(), InvalidBasicBlockIndex); + ancestor = std::vector<BasicBlockIndex>(nodes.size(), InvalidBasicBlockIndex); + idom = std::vector<BasicBlockIndex>(nodes.size(), InvalidBasicBlockIndex); + samedom = std::vector<BasicBlockIndex>(nodes.size(), InvalidBasicBlockIndex); + best = std::vector<BasicBlockIndex>(nodes.size(), InvalidBasicBlockIndex); + + QHash<BasicBlockIndex, std::vector<BasicBlockIndex> > bucket; + + DFS(nodes.first()->index); Q_ASSERT(N == nodes.size()); // fails with unreachable nodes, but those should have been removed before. for (int i = N - 1; i > 0; --i) { - BasicBlock *n = vertex[i]; - BasicBlock *p = parent[n]; - BasicBlock *s = p; - - foreach (BasicBlock *v, n->in) { - BasicBlock *ss; - if (dfnum[v] <= dfnum[n]) - ss = v; + BasicBlockIndex n = vertex[i]; + BasicBlockIndex p = parent[n]; + BasicBlockIndex s = p; + + foreach (BasicBlock *v, nodes.at(n)->in) { + BasicBlockIndex ss = InvalidBasicBlockIndex; + if (dfnum[v->index] <= dfnum[n]) + ss = v->index; else - ss = semi[ancestorWithLowestSemi(v)]; + ss = semi[ancestorWithLowestSemi(v->index)]; if (dfnum[ss] < dfnum[s]) s = ss; } semi[n] = s; - bucket[s].insert(n); + bucket[s].push_back(n); link(p, n); - foreach (BasicBlock *v, bucket[p]) { - BasicBlock *y = ancestorWithLowestSemi(v); - BasicBlock *semi_v = semi[v]; - if (semi[y] == semi_v) - idom[v] = semi_v; - else - samedom[v] = y; + if (bucket.contains(p)) { + foreach (BasicBlockIndex v, bucket[p]) { + BasicBlockIndex y = ancestorWithLowestSemi(v); + BasicBlockIndex semi_v = semi[v]; + if (semi[y] == semi_v) + idom[v] = semi_v; + else + samedom[v] = y; + } + bucket.remove(p); } - bucket[p].clear(); } + +#if defined(SHOW_SSA) + for (int i = 0; i < nodes.size(); ++i) + qDebug("\tL%d: ancestor = %d, semi = %d, samedom = %d", i, ancestor[i], semi[i], samedom[i]); +#endif // SHOW_SSA + for (int i = 1; i < N; ++i) { - BasicBlock *n = vertex[i]; - Q_ASSERT(ancestor[n] && ((semi[n] && dfnum[ancestor[n]] <= dfnum[semi[n]]) || semi[n] == n)); - Q_ASSERT(bucket[n].isEmpty()); - if (BasicBlock *sdn = samedom[n]) + BasicBlockIndex n = vertex[i]; + Q_ASSERT(n != InvalidBasicBlockIndex); + Q_ASSERT(!bucket.contains(n)); + Q_ASSERT(ancestor[n] != InvalidBasicBlockIndex + && ((semi[n] != InvalidBasicBlockIndex + && dfnum[ancestor[n]] <= dfnum[semi[n]]) || semi[n] == n)); + BasicBlockIndex sdn = samedom[n]; + if (sdn != InvalidBasicBlockIndex) idom[n] = idom[sdn]; } -#ifdef SHOW_SSA +#if defined(SHOW_SSA) qout << "Immediate dominators:" << endl; foreach (BasicBlock *to, nodes) { qout << '\t'; - if (BasicBlock *from = idom.value(to)) - qout << from->index; + BasicBlockIndex from = idom.at(to->index); + if (from != InvalidBasicBlockIndex) + qout << from; else qout << "(none)"; qout << " -> " << to->index << endl; @@ -396,55 +433,72 @@ class DominatorTree { } struct NodeProgress { - QSet<BasicBlock *> children; - QSet<BasicBlock *> todo; + std::vector<BasicBlockIndex> children; + std::vector<BasicBlockIndex> todo; }; - void computeDF(const QVector<BasicBlock *> &nodes) { - QHash<BasicBlock *, NodeProgress> nodeStatus; + void computeDF() { + // compute children of each node in the dominator tree + std::vector<std::vector<BasicBlockIndex> > children; // BasicBlock index -> children + children.resize(nodes.size()); + foreach (BasicBlock *n, nodes) { + const BasicBlockIndex nodeIndex = n->index; + Q_ASSERT(nodes.at(nodeIndex) == n); + const BasicBlockIndex nodeDominator = idom[nodeIndex]; + if (nodeDominator == InvalidBasicBlockIndex) + continue; // there is no dominator to add this node to as a child (e.g. the start node) + children[nodeDominator].push_back(nodeIndex); + } + + // Fill the worklist and initialize the node status for each basic-block + QHash<BasicBlockIndex, NodeProgress> nodeStatus; nodeStatus.reserve(nodes.size()); - QVector<BasicBlock *> worklist; + std::vector<BasicBlockIndex> worklist; worklist.reserve(nodes.size() * 2); for (int i = 0, ei = nodes.size(); i != ei; ++i) { - BasicBlock *node = nodes[i]; - worklist.append(node); - NodeProgress &np = nodeStatus[node]; - np.children = children[node]; - np.todo = children[node]; + BasicBlockIndex nodeIndex = nodes[i]->index; + worklist.push_back(nodeIndex); + NodeProgress &np = nodeStatus[nodeIndex]; + np.children = children[nodeIndex]; + np.todo = children[nodeIndex]; } - while (!worklist.isEmpty()) { - BasicBlock *node = worklist.last(); + std::vector<bool> DF_done(nodes.size(), false); + + while (!worklist.empty()) { + BasicBlockIndex node = worklist.back(); - if (DF.contains(node)) { - worklist.removeLast(); + if (DF_done[node]) { + worklist.pop_back(); continue; } NodeProgress &np = nodeStatus[node]; - QSet<BasicBlock *>::iterator it = np.todo.begin(); + std::vector<BasicBlockIndex>::iterator it = np.todo.begin(); while (it != np.todo.end()) { - if (DF.contains(*it)) { + if (DF_done[*it]) { it = np.todo.erase(it); } else { - worklist.append(*it); + worklist.push_back(*it); break; } } - if (np.todo.isEmpty()) { + if (np.todo.empty()) { QSet<BasicBlock *> S; - foreach (BasicBlock *y, node->out) - if (idom[y] != node) - if (!S.contains(y)) - S.insert(y); - foreach (BasicBlock *child, np.children) - foreach (BasicBlock *w, DF[child]) - if (!dominates(node, w) || node == w) - if (!S.contains(w)) - S.insert(w); - DF.insert(node, S); - worklist.removeLast(); + foreach (BasicBlock *y, nodes[node]->out) + if (idom[y->index] != node) + S.insert(y); + foreach (BasicBlockIndex child, np.children) { + foreach (BasicBlock *w, DF[child]) { + const BasicBlockIndex wIndex = w->index; + if (node == wIndex || !dominates(node, w->index)) + S.insert(w); + } + } + DF[node] = S; + DF_done[node] = true; + worklist.pop_back(); } } @@ -452,7 +506,7 @@ class DominatorTree { qout << "Dominator Frontiers:" << endl; foreach (BasicBlock *n, nodes) { qout << "\tDF[" << n->index << "]: {"; - QList<BasicBlock *> SList = DF[n].values(); + QList<BasicBlock *> SList = DF[n->index].values(); for (int i = 0; i < SList.size(); ++i) { if (i > 0) qout << ", "; @@ -463,7 +517,7 @@ class DominatorTree { #endif // SHOW_SSA #if !defined(QT_NO_DEBUG) && defined(CAN_TAKE_LOSTS_OF_TIME) foreach (BasicBlock *n, nodes) { - foreach (BasicBlock *fBlock, DF[n]) { + foreach (BasicBlock *fBlock, DF[n->index]) { Q_ASSERT(!dominates(n, fBlock) || fBlock == n); bool hasDominatedSucc = false; foreach (BasicBlock *succ, fBlock->in) { @@ -473,7 +527,7 @@ class DominatorTree { } } if (!hasDominatedSucc) { - qout << fBlock->index << " in DF[" << n->index << "] has no dominated predecessors" << endl; + qout << fBlock << " in DF[" << n->index << "] has no dominated predecessors" << endl; } Q_ASSERT(hasDominatedSucc); } @@ -481,35 +535,33 @@ class DominatorTree { #endif // !QT_NO_DEBUG } - QHash<BasicBlock *, QSet<BasicBlock *> > children; - QHash<BasicBlock *, QSet<BasicBlock *> > DF; - public: DominatorTree(const QVector<BasicBlock *> &nodes) - : N(0) + : nodes(nodes) + , N(0) { - calculateIDoms(nodes); - - // compute children of n - foreach (BasicBlock *n, nodes) { - QSet<BasicBlock *> &c = children[idom[n]]; - if (!c.contains(n)) - c.insert(n); - } - - computeDF(nodes); + DF.resize(nodes.size()); + calculateIDoms(); + computeDF(); } QSet<BasicBlock *> operator[](BasicBlock *n) const { - return DF[n]; + return DF[n->index]; } BasicBlock *immediateDominator(BasicBlock *bb) const { - return idom[bb]; + return nodes[idom[bb->index]]; } bool dominates(BasicBlock *dominator, BasicBlock *dominated) const { - for (BasicBlock *it = dominated; it; it = idom[it]) { + // The index of the basic blocks might have changed, or the nodes array might have changed, + // or the block got deleted, so get the index from our copy of the array. + return dominates(nodes.indexOf(dominator), nodes.indexOf(dominated)); + } + +private: + bool dominates(BasicBlockIndex dominator, BasicBlockIndex dominated) const { + for (BasicBlockIndex it = dominated; it != InvalidBasicBlockIndex; it = idom[it]) { if (it == dominator) return true; } @@ -1581,7 +1633,8 @@ public: BasicBlock *bb = function->basicBlocks[i]; if (i == 0 || !bb->in.isEmpty()) foreach (Stmt *s, bb->statements) - _worklist.insert(s); + if (!s->asJump()) + _worklist.insert(s); } while (!_worklist.isEmpty()) { @@ -2687,6 +2740,11 @@ namespace { /// Important: this assumes that there are no critical edges in the control-flow graph! void purgeBB(BasicBlock *bb, Function *func, DefUsesCalculator &defUses, QVector<Stmt *> &W) { + // TODO: change this to mark the block as deleted, but leave it alone so that other references + // won't be dangling pointers. + // TODO: after the change above: if we keep on detaching the block from predecessors or + // successors, update the DominatorTree too. + // don't purge blocks that are entry points for catch statements. They might not be directly // connected, but are required anyway if (bb->isExceptionHandler) @@ -2826,6 +2884,8 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses) foreach (BasicBlock *bb, function->basicBlocks) { for (int i = 0, ei = bb->statements.size(); i != ei; ++i) { Stmt **s = &bb->statements[i]; + if ((*s)->asJump()) + continue; // nothing do do there W.append(*s); ref.insert(*s, s); } |