aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4jsir.cpp
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@digia.com>2014-03-21 10:56:52 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-04-15 15:31:23 +0200
commit377aeea46cb90f84e5a0e867e5f68cd9f89f56b1 (patch)
tree6e5990fe8b64024c9e943693897d58877f9e5888 /src/qml/compiler/qv4jsir.cpp
parent63f757faea7008e478e0a1edea4f0ae79aaba5f7 (diff)
V4 IR: clean up basic-block management and statement access.
BasicBlocks have an index property which points to the index of that basic block in the container array in Function. This property can be used to store calculated information about basic blocks in a vector, where the vector index corresponds to the basic block index. This is a lot cheaper than storing any information in a QHash<BasicBlock *, ....>. However, this numbering requires that no re-ordering or deletion of blocks happens. This change cleans up all that handling which was scattered over a number of places. Change-Id: I337abd39c030b9d30c82b7bbcf2ba89e50a08e63 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/compiler/qv4jsir.cpp')
-rw-r--r--src/qml/compiler/qv4jsir.cpp169
1 files changed, 152 insertions, 17 deletions
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index efce64bf7a..a067a95104 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -165,10 +165,12 @@ struct RemoveSharedExpressions: IR::StmtVisitor, IR::ExprVisitor
{
subexpressions.clear();
- foreach (BasicBlock *block, function->basicBlocks) {
+ foreach (BasicBlock *block, function->basicBlocks()) {
+ if (block->isRemoved())
+ continue;
clone.setBasicBlock(block);
- foreach (Stmt *s, block->statements) {
+ foreach (Stmt *s, block->statements()) {
s->accept(this);
}
}
@@ -586,7 +588,7 @@ void Move::dump(QTextStream &out, Mode mode)
void Jump::dump(QTextStream &out, Mode mode)
{
Q_UNUSED(mode);
- out << "goto " << 'L' << target->index << ';';
+ out << "goto " << 'L' << target->index() << ';';
}
void CJump::dump(QTextStream &out, Mode mode)
@@ -595,9 +597,9 @@ void CJump::dump(QTextStream &out, Mode mode)
out << "if (";
cond->dump(out);
if (mode == HIR)
- out << ") goto " << 'L' << iftrue->index << "; else goto " << 'L' << iffalse->index << ';';
+ out << ") goto " << 'L' << iftrue->index() << "; else goto " << 'L' << iffalse->index() << ';';
else
- out << ") goto " << 'L' << iftrue->index << ";";
+ out << ") goto " << 'L' << iftrue->index() << ";";
}
void Ret::dump(QTextStream &out, Mode)
@@ -654,15 +656,37 @@ void Module::setFileName(const QString &name)
}
}
+Function::Function(Module *module, Function *outer, const QString &name)
+ : module(module)
+ , pool(&module->pool)
+ , tempCount(0)
+ , maxNumberOfArguments(0)
+ , outer(outer)
+ , insideWithOrCatch(0)
+ , hasDirectEval(false)
+ , usesArgumentsObject(false)
+ , isStrict(false)
+ , isNamedExpression(false)
+ , hasTry(false)
+ , hasWith(false)
+ , unused(0)
+ , line(-1)
+ , column(-1)
+ , _allBasicBlocks(0)
+{
+ this->name = newString(name);
+ _basicBlocks.reserve(8);
+}
+
Function::~Function()
{
- // destroy the Stmt::Data blocks manually, because memory pool cleanup won't
- // call the Stmt destructors.
- foreach (IR::BasicBlock *b, basicBlocks)
- foreach (IR::Stmt *s, b->statements)
- s->destroyData();
+ if (_allBasicBlocks) {
+ qDeleteAll(*_allBasicBlocks);
+ delete _allBasicBlocks;
+ } else {
+ qDeleteAll(_basicBlocks);
+ }
- qDeleteAll(basicBlocks);
pool = 0;
module = 0;
}
@@ -676,7 +700,24 @@ const QString *Function::newString(const QString &text)
BasicBlock *Function::newBasicBlock(BasicBlock *containingLoop, BasicBlock *catchBlock, BasicBlockInsertMode mode)
{
BasicBlock *block = new BasicBlock(this, containingLoop, catchBlock);
- return mode == InsertBlock ? insertBasicBlock(block) : block;
+ return mode == InsertBlock ? addBasicBlock(block) : block;
+}
+
+BasicBlock *Function::addBasicBlock(BasicBlock *block)
+{
+ Q_ASSERT(block->index() < 0);
+ block->setIndex(_basicBlocks.size());
+ _basicBlocks.append(block);
+ return block;
+}
+
+int Function::liveBasicBlocksCount() const
+{
+ int count = 0;
+ foreach (BasicBlock *bb, basicBlocks())
+ if (!bb->isRemoved())
+ ++count;
+ return count;
}
void Function::dump(QTextStream &out, Stmt::Mode mode)
@@ -689,7 +730,7 @@ void Function::dump(QTextStream &out, Stmt::Mode mode)
out << "\treceive " << *formal << ';' << endl;
foreach (const QString *local, locals)
out << "\tlocal " << *local << ';' << endl;
- foreach (BasicBlock *bb, basicBlocks)
+ foreach (BasicBlock *bb, basicBlocks())
bb->dump(out, mode);
out << '}' << endl;
}
@@ -708,13 +749,35 @@ int Function::indexOfArgument(const QStringRef &string) const
}
return -1;
}
+
+void Function::setScheduledBlocks(const QVector<BasicBlock *> &scheduled)
+{
+ Q_ASSERT(!_allBasicBlocks);
+ _allBasicBlocks = new QVector<BasicBlock *>(basicBlocks());
+ _basicBlocks = scheduled;
+}
+
+void Function::renumberBasicBlocks()
+{
+ for (int i = 0, ei = basicBlockCount(); i != ei; ++i)
+ basicBlock(i)->changeIndex(i);
+}
+
+BasicBlock::~BasicBlock()
+{
+ foreach (Stmt *s, _statements)
+ s->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, 0);
return e;
@@ -722,6 +785,7 @@ Temp *BasicBlock::TEMP(unsigned index)
Temp *BasicBlock::ARG(unsigned index, unsigned scope)
{
+ Q_ASSERT(!isRemoved());
Temp *e = function->New<Temp>();
e->init(scope ? Temp::ScopedFormal : Temp::Formal, index, scope);
return e;
@@ -729,6 +793,7 @@ Temp *BasicBlock::ARG(unsigned index, unsigned scope)
Temp *BasicBlock::LOCAL(unsigned index, unsigned scope)
{
+ Q_ASSERT(!isRemoved());
Temp *e = function->New<Temp>();
e->init(scope ? Temp::ScopedLocal : Temp::Local, index, scope);
return e;
@@ -736,6 +801,7 @@ Temp *BasicBlock::LOCAL(unsigned index, unsigned scope)
Expr *BasicBlock::CONST(Type type, double value)
{
+ Q_ASSERT(!isRemoved());
Const *e = function->New<Const>();
if (type == NumberType) {
int ival = (int)value;
@@ -756,6 +822,7 @@ Expr *BasicBlock::CONST(Type type, double value)
Expr *BasicBlock::STRING(const QString *value)
{
+ Q_ASSERT(!isRemoved());
String *e = function->New<String>();
e->init(value);
return e;
@@ -763,6 +830,7 @@ Expr *BasicBlock::STRING(const QString *value)
Expr *BasicBlock::REGEXP(const QString *value, int flags)
{
+ Q_ASSERT(!isRemoved());
RegExp *e = function->New<RegExp>();
e->init(value, flags);
return e;
@@ -770,6 +838,7 @@ Expr *BasicBlock::REGEXP(const QString *value, int flags)
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;
@@ -777,6 +846,7 @@ Name *BasicBlock::NAME(const QString &id, quint32 line, quint32 column)
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;
@@ -785,6 +855,7 @@ Name *BasicBlock::GLOBALNAME(const QString &id, quint32 line, quint32 column)
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;
@@ -792,6 +863,7 @@ Name *BasicBlock::NAME(Name::Builtin builtin, quint32 line, quint32 column)
Closure *BasicBlock::CLOSURE(int functionInModule)
{
+ Q_ASSERT(!isRemoved());
Closure *clos = function->New<Closure>();
clos->init(functionInModule, function->module->functions.at(functionInModule)->name);
return clos;
@@ -799,6 +871,7 @@ Closure *BasicBlock::CLOSURE(int functionInModule)
Expr *BasicBlock::CONVERT(Expr *expr, Type type)
{
+ Q_ASSERT(!isRemoved());
Convert *e = function->New<Convert>();
e->init(expr, type);
return e;
@@ -806,6 +879,7 @@ Expr *BasicBlock::CONVERT(Expr *expr, Type type)
Expr *BasicBlock::UNOP(AluOp op, Expr *expr)
{
+ Q_ASSERT(!isRemoved());
Unop *e = function->New<Unop>();
e->init(op, expr);
return e;
@@ -813,6 +887,7 @@ Expr *BasicBlock::UNOP(AluOp op, Expr *expr)
Expr *BasicBlock::BINOP(AluOp op, Expr *left, Expr *right)
{
+ Q_ASSERT(!isRemoved());
Binop *e = function->New<Binop>();
e->init(op, left, right);
return e;
@@ -820,6 +895,7 @@ Expr *BasicBlock::BINOP(AluOp op, Expr *left, Expr *right)
Expr *BasicBlock::CALL(Expr *base, ExprList *args)
{
+ Q_ASSERT(!isRemoved());
Call *e = function->New<Call>();
e->init(base, args);
int argc = 0;
@@ -831,6 +907,7 @@ Expr *BasicBlock::CALL(Expr *base, ExprList *args)
Expr *BasicBlock::NEW(Expr *base, ExprList *args)
{
+ Q_ASSERT(!isRemoved());
New *e = function->New<New>();
e->init(base, args);
return e;
@@ -838,6 +915,7 @@ Expr *BasicBlock::NEW(Expr *base, ExprList *args)
Expr *BasicBlock::SUBSCRIPT(Expr *base, Expr *index)
{
+ Q_ASSERT(!isRemoved());
Subscript *e = function->New<Subscript>();
e->init(base, index);
return e;
@@ -845,6 +923,7 @@ Expr *BasicBlock::SUBSCRIPT(Expr *base, Expr *index)
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;
@@ -852,6 +931,7 @@ Expr *BasicBlock::MEMBER(Expr *base, const QString *name, QQmlPropertyData *prop
Stmt *BasicBlock::EXP(Expr *expr)
{
+ Q_ASSERT(!isRemoved());
if (isTerminated())
return 0;
@@ -863,6 +943,7 @@ Stmt *BasicBlock::EXP(Expr *expr)
Stmt *BasicBlock::MOVE(Expr *target, Expr *source)
{
+ Q_ASSERT(!isRemoved());
if (isTerminated())
return 0;
@@ -874,6 +955,7 @@ Stmt *BasicBlock::MOVE(Expr *target, Expr *source)
Stmt *BasicBlock::JUMP(BasicBlock *target)
{
+ Q_ASSERT(!isRemoved());
if (isTerminated())
return 0;
@@ -892,6 +974,7 @@ Stmt *BasicBlock::JUMP(BasicBlock *target)
Stmt *BasicBlock::CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse)
{
+ Q_ASSERT(!isRemoved());
if (isTerminated())
return 0;
@@ -921,6 +1004,7 @@ Stmt *BasicBlock::CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse)
Stmt *BasicBlock::RET(Temp *expr)
{
+ Q_ASSERT(!isRemoved());
if (isTerminated())
return 0;
@@ -932,11 +1016,11 @@ Stmt *BasicBlock::RET(Temp *expr)
void BasicBlock::dump(QTextStream &out, Stmt::Mode mode)
{
- out << 'L' << index << ':';
+ out << 'L' << index() << ':';
if (catchBlock)
- out << " (catchBlock L" << catchBlock->index << ")";
+ out << " (catchBlock L" << catchBlock->index() << ")";
out << endl;
- foreach (Stmt *s, statements) {
+ foreach (Stmt *s, statements()) {
out << '\t';
s->dump(out, mode);
@@ -947,11 +1031,62 @@ void BasicBlock::dump(QTextStream &out, Stmt::Mode mode)
}
}
+void BasicBlock::setStatements(const QVector<Stmt *> &newStatements)
+{
+ Q_ASSERT(!isRemoved());
+ Q_ASSERT(newStatements.size() >= _statements.size());
+ _statements = newStatements;
+}
+
void BasicBlock::appendStatement(Stmt *statement)
{
+ Q_ASSERT(!isRemoved());
if (nextLocation.isValid())
statement->location = nextLocation;
- statements.append(statement);
+ _statements.append(statement);
+}
+
+void BasicBlock::prependStatement(Stmt *stmt)
+{
+ Q_ASSERT(!isRemoved());
+ _statements.prepend(stmt);
+}
+
+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());
+ _statements[index] = newStmt;
+}
+
+void BasicBlock::removeStatement(Stmt *stmt)
+{
+ Q_ASSERT(!isRemoved());
+ _statements.remove(_statements.indexOf(stmt));
+}
+
+void BasicBlock::removeStatement(int idx)
+{
+ Q_ASSERT(!isRemoved());
+ _statements.remove(idx);
}
CloneExpr::CloneExpr(BasicBlock *block)