aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4ssa.cpp
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@digia.com>2014-05-07 16:42:49 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-06-02 12:14:40 +0200
commitb366e5509b2dcc6df73fc20d4167d663c6cad763 (patch)
tree28f043d39a60be5be571f7d8c49d00023305177f /src/qml/compiler/qv4ssa.cpp
parent39c8ee0db49001d863f43c7da52ad2dbdb5113ac (diff)
V4 IR: make the local-with-temp substitution into a separate pass.
This makes it easier to turn it off when needed. Change-Id: I1a9f2882dd7a1ad7bc76143e3c44e4677e49357a Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/compiler/qv4ssa.cpp')
-rw-r--r--src/qml/compiler/qv4ssa.cpp81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index 4e163b5c22..de66456680 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -3683,6 +3683,85 @@ void removeUnreachleBlocks(IR::Function *function)
function->setScheduledBlocks(newSchedule);
function->renumberBasicBlocks();
}
+
+class ConvertArgLocals: protected StmtVisitor, protected ExprVisitor
+{
+public:
+ ConvertArgLocals(IR::Function *function)
+ : function(function)
+ {
+ tempForLocal.resize(function->locals.size(), -1);
+ }
+
+ void toTemps()
+ {
+ if (function->variablesCanEscape())
+ return;
+
+ foreach (BasicBlock *bb, function->basicBlocks())
+ if (!bb->isRemoved())
+ foreach (Stmt *s, bb->statements())
+ s->accept(this);
+
+ function->locals.clear();
+ }
+
+protected:
+ virtual void visitConst(Const *) {}
+ virtual void visitString(IR::String *) {}
+ virtual void visitRegExp(IR::RegExp *) {}
+ virtual void visitName(Name *) {}
+ virtual void visitTemp(Temp *) {}
+ virtual void visitArgLocal(ArgLocal *) {}
+ virtual void visitClosure(Closure *) {}
+ virtual void visitConvert(Convert *e) { check(e->expr); }
+ virtual void visitUnop(Unop *e) { check(e->expr); }
+ virtual void visitBinop(Binop *e) { check(e->left); check(e->right); }
+ virtual void visitCall(Call *e) {
+ check(e->base);
+ for (ExprList *it = e->args; it; it = it->next)
+ check(it->expr);
+ }
+ virtual void visitNew(New *e) {
+ check(e->base);
+ for (ExprList *it = e->args; it; it = it->next)
+ check(it->expr);
+ }
+ virtual void visitSubscript(Subscript *e) { check(e->base); check(e->index); }
+ virtual void visitMember(Member *e) { check(e->base); }
+ virtual void visitExp(Exp *s) { check(s->expr); }
+ virtual void visitMove(Move *s) { check(s->target); check(s->source); }
+ virtual void visitJump(Jump *) {}
+ virtual void visitCJump(CJump *s) { check(s->cond); }
+ virtual void visitRet(Ret *s) { check(s->expr); }
+ virtual void visitPhi(Phi *) {
+ Q_UNREACHABLE();
+ }
+
+private:
+ void check(Expr *&e) {
+ if (ArgLocal *al = e->asArgLocal()) {
+ if (al->kind == ArgLocal::Local) {
+ Temp *t = function->New<Temp>();
+ t->init(Temp::VirtualRegister, fetchTempForLocal(al->index));
+ e = t;
+ }
+ } else {
+ e->accept(this);
+ }
+ }
+
+ int fetchTempForLocal(int local)
+ {
+ int &ref = tempForLocal[local];
+ if (ref == -1)
+ ref = function->tempCount++;
+ return ref;
+ }
+
+ IR::Function *function;
+ std::vector<int> tempForLocal;
+};
} // anonymous namespace
void LifeTimeInterval::setFrom(Stmt *from) {
@@ -3853,6 +3932,8 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine)
if (!function->hasTry && !function->hasWith && !function->module->debugMode && doSSA) {
// qout << "SSA for " << (function->name ? qPrintable(*function->name) : "<anonymous>") << endl;
+ ConvertArgLocals(function).toTemps();
+
// Calculate the dominator tree:
DominatorTree df(function);