aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h1
-rw-r--r--src/qml/compiler/qv4codegen.cpp63
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp182
-rw-r--r--src/qml/compiler/qv4isel_moth_p.h86
-rw-r--r--src/qml/compiler/qv4isel_p.cpp108
-rw-r--r--src/qml/compiler/qv4isel_p.h84
-rw-r--r--src/qml/compiler/qv4isel_util_p.h1
-rw-r--r--src/qml/compiler/qv4jsir.cpp45
-rw-r--r--src/qml/compiler/qv4jsir_p.h78
-rw-r--r--src/qml/compiler/qv4ssa.cpp155
-rw-r--r--src/qml/jit/qv4assembler.cpp49
-rw-r--r--src/qml/jit/qv4assembler_p.h208
-rw-r--r--src/qml/jit/qv4binop.cpp50
-rw-r--r--src/qml/jit/qv4binop_p.h8
-rw-r--r--src/qml/jit/qv4isel_masm.cpp314
-rw-r--r--src/qml/jit/qv4isel_masm_p.h137
-rw-r--r--src/qml/jit/qv4regalloc.cpp149
-rw-r--r--src/qml/jit/qv4unop.cpp35
-rw-r--r--src/qml/jit/qv4unop_p.h8
19 files changed, 946 insertions, 815 deletions
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index fb8ac94fcd..3d8c35781f 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -394,6 +394,7 @@ private:
virtual void visitClosure(QV4::IR::Closure *closure);
virtual void visitTemp(QV4::IR::Temp *) {}
+ virtual void visitArgLocal(QV4::IR::ArgLocal *) {}
virtual void visitMove(QV4::IR::Move *s) {
s->source->accept(this);
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index fdc4d5c9f2..421dcf6775 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -509,8 +509,8 @@ IR::Expr *Codegen::member(IR::Expr *base, const QString *name)
if (hasError)
return 0;
- if (base->asTemp() /*|| base->asName()*/)
- return _block->MEMBER(base->asTemp(), name);
+ if (base->asTemp() || base->asArgLocal())
+ return _block->MEMBER(base, name);
else {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), base);
@@ -523,25 +523,26 @@ IR::Expr *Codegen::subscript(IR::Expr *base, IR::Expr *index)
if (hasError)
return 0;
- if (! base->asTemp()) {
+ if (! base->asTemp() || base->asArgLocal()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), base);
base = _block->TEMP(t);
}
- if (! index->asTemp()) {
+ if (! index->asTemp() || index->asArgLocal()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), index);
index = _block->TEMP(t);
}
- Q_ASSERT(base->asTemp() && index->asTemp());
+ Q_ASSERT(base->asTemp() || base->asArgLocal());
+ Q_ASSERT(index->asTemp() || index->asArgLocal());
return _block->SUBSCRIPT(base->asTemp(), index->asTemp());
}
IR::Expr *Codegen::argument(IR::Expr *expr)
{
- if (expr && ! expr->asTemp()) {
+ if (expr && !expr->asTemp() && !expr->asArgLocal()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), expr);
expr = _block->TEMP(t);
@@ -555,7 +556,7 @@ IR::Expr *Codegen::reference(IR::Expr *expr)
if (hasError)
return 0;
- if (expr && !expr->asTemp() && !expr->asName() && !expr->asMember() && !expr->asSubscript()) {
+ if (expr && !expr->asTemp() && !expr->asArgLocal() && !expr->asName() && !expr->asMember() && !expr->asSubscript()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), expr);
expr = _block->TEMP(t);
@@ -591,13 +592,13 @@ IR::Expr *Codegen::unop(IR::AluOp op, IR::Expr *expr)
}
}
}
- if (! expr->asTemp()) {
+ if (!expr->asTemp() && !expr->asArgLocal()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), expr);
expr = _block->TEMP(t);
}
- Q_ASSERT(expr->asTemp());
- return _block->UNOP(op, expr->asTemp());
+ Q_ASSERT(expr->asTemp() || expr->asArgLocal());
+ return _block->UNOP(op, expr);
}
IR::Expr *Codegen::binop(IR::AluOp op, IR::Expr *left, IR::Expr *right)
@@ -655,20 +656,20 @@ IR::Expr *Codegen::binop(IR::AluOp op, IR::Expr *left, IR::Expr *right)
}
}
- if (!left->asTemp()) {
+ if (!left->asTemp() && !left->asArgLocal()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), left);
left = _block->TEMP(t);
}
- if (!right->asTemp()) {
+ if (!right->asTemp() && !right->asArgLocal()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), right);
right = _block->TEMP(t);
}
- Q_ASSERT(left->asTemp());
- Q_ASSERT(right->asTemp());
+ Q_ASSERT(left->asTemp() || left->asArgLocal());
+ Q_ASSERT(right->asTemp() || right->asArgLocal());
return _block->BINOP(op, left, right);
}
@@ -693,12 +694,12 @@ void Codegen::move(IR::Expr *target, IR::Expr *source, IR::AluOp op)
return;
}
- if (!source->asTemp() && !source->asConst() && !target->asTemp()) {
+ if (!source->asTemp() && !source->asConst() && !target->asTemp() && !source->asArgLocal() && !target->asArgLocal()) {
unsigned t = _block->newTemp();
_block->MOVE(_block->TEMP(t), source);
source = _block->TEMP(t);
}
- if (source->asConst() && !target->asTemp()) {
+ if (source->asConst() && !target->asTemp() && !target->asArgLocal()) {
unsigned t = _block->newTemp();
_block->MOVE(_block->TEMP(t), source);
source = _block->TEMP(t);
@@ -749,7 +750,7 @@ void Codegen::statement(ExpressionNode *ast)
if (r.format == ex) {
if (r->asCall()) {
_block->EXP(*r); // the nest nx representation for calls is EXP(CALL(c..))
- } else if (r->asTemp()) {
+ } else if (r->asTemp() || r->asArgLocal()) {
// there is nothing to do
} else {
unsigned t = _block->newTemp();
@@ -1065,7 +1066,7 @@ bool Codegen::visit(ArrayLiteral *ast)
current = arg;
IR::Expr *exp = *expr;
- if (exp->asTemp() || exp->asConst()) {
+ if (exp->asTemp() || expr->asArgLocal() || exp->asConst()) {
current->expr = exp;
} else {
unsigned value = _block->newTemp();
@@ -1236,7 +1237,7 @@ bool Codegen::visit(BinaryExpression *ast)
case QSOperator::Lt:
case QSOperator::StrictEqual:
case QSOperator::StrictNotEqual: {
- if (!left->asTemp() && !left->asConst()) {
+ if (!left->asTemp() && !left->asArgLocal() && !left->asConst()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), left);
left = _block->TEMP(t);
@@ -1270,7 +1271,7 @@ bool Codegen::visit(BinaryExpression *ast)
case QSOperator::RShift:
case QSOperator::Sub:
case QSOperator::URShift: {
- if (!left->asTemp() && !left->asConst()) {
+ if (!left->asTemp() && !left->asArgLocal() && !left->asConst()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), left);
left = _block->TEMP(t);
@@ -1347,8 +1348,8 @@ bool Codegen::visit(DeleteExpression *ast)
IR::Expr* expr = *expression(ast->expression);
// Temporaries cannot be deleted
- IR::Temp *t = expr->asTemp();
- if (t && t->index < static_cast<unsigned>(_env->members.size())) {
+ IR::ArgLocal *al = expr->asArgLocal();
+ if (al && al->index < static_cast<unsigned>(_env->members.size())) {
// Trying to delete a function argument might throw.
if (_function->isStrict) {
throwSyntaxError(ast->deleteToken, QStringLiteral("Delete of an unqualified identifier in strict mode."));
@@ -1375,7 +1376,9 @@ bool Codegen::visit(DeleteExpression *ast)
_expr.code = _block->CONST(IR::BoolType, 1);
return false;
}
- if (expr->asTemp() && expr->asTemp()->index >= static_cast<unsigned>(_env->members.size())) {
+ if (expr->asTemp() ||
+ (expr->asArgLocal() &&
+ expr->asArgLocal()->index >= static_cast<unsigned>(_env->members.size()))) {
_expr.code = _block->CONST(IR::BoolType, 1);
return false;
}
@@ -1435,10 +1438,10 @@ IR::Expr *Codegen::identifier(const QString &name, int line, int col)
int index = e->findMember(name);
Q_ASSERT (index < e->members.size());
if (index != -1) {
- IR::Temp *t = _block->LOCAL(index, scope);
+ IR::ArgLocal *al = _block->LOCAL(index, scope);
if (name == QStringLiteral("arguments") || name == QStringLiteral("eval"))
- t->isArgumentsOrEval = true;
- return t;
+ al->isArgumentsOrEval = true;
+ return al;
}
const int argIdx = f->indexOfArgument(&name);
if (argIdx != -1)
@@ -1497,7 +1500,7 @@ bool Codegen::visit(NewExpression *ast)
Result base = expression(ast->expression);
IR::Expr *expr = *base;
- if (expr && !expr->asTemp() && !expr->asName() && !expr->asMember()) {
+ if (expr && !expr->asTemp() && !expr->asArgLocal() && !expr->asName() && !expr->asMember()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), expr);
expr = _block->TEMP(t);
@@ -1513,7 +1516,7 @@ bool Codegen::visit(NewMemberExpression *ast)
Result base = expression(ast->base);
IR::Expr *expr = *base;
- if (expr && !expr->asTemp() && !expr->asName() && !expr->asMember()) {
+ if (expr && !expr->asTemp() && !expr->asArgLocal() && !expr->asName() && !expr->asMember()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), expr);
expr = _block->TEMP(t);
@@ -2798,8 +2801,8 @@ bool Codegen::throwSyntaxErrorOnEvalOrArgumentsInStrictMode(IR::Expr *expr, cons
if (IR::Name *n = expr->asName()) {
if (*n->id != QLatin1String("eval") && *n->id != QLatin1String("arguments"))
return false;
- } else if (IR::Temp *t = expr->asTemp()) {
- if (!t->isArgumentsOrEval)
+ } else if (IR::ArgLocal *al = expr->asArgLocal()) {
+ if (!al->isArgumentsOrEval)
return false;
} else {
return false;
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index 9288008632..f5038c8ae1 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -456,7 +456,7 @@ QV4::CompiledData::CompilationUnit *InstructionSelection::backendCompileStep()
return compilationUnit;
}
-void InstructionSelection::callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result)
+void InstructionSelection::callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result)
{
Instruction::CallValue call;
prepareCallArgs(args, call.argc);
@@ -467,7 +467,7 @@ void InstructionSelection::callValue(IR::Temp *value, IR::ExprList *args, IR::Te
}
void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR::ExprList *args,
- IR::Temp *result)
+ IR::Expr *result)
{
if (useFastLookups) {
Instruction::CallPropertyLookup call;
@@ -490,7 +490,7 @@ void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR:
}
void InstructionSelection::callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args,
- IR::Temp *result)
+ IR::Expr *result)
{
// call the property on the loaded base
Instruction::CallElement call;
@@ -502,7 +502,7 @@ void InstructionSelection::callSubscript(IR::Expr *base, IR::Expr *index, IR::Ex
addInstruction(call);
}
-void InstructionSelection::convertType(IR::Temp *source, IR::Temp *target)
+void InstructionSelection::convertType(IR::Expr *source, IR::Expr *target)
{
// FIXME: do something more useful with this info
if (target->type & IR::NumberType && !(source->type & IR::NumberType))
@@ -513,14 +513,14 @@ void InstructionSelection::convertType(IR::Temp *source, IR::Temp *target)
void InstructionSelection::constructActivationProperty(IR::Name *func,
IR::ExprList *args,
- IR::Temp *result)
+ IR::Expr *target)
{
if (useFastLookups && func->global) {
Instruction::ConstructGlobalLookup call;
call.index = registerGlobalGetterLookup(*func->id);
prepareCallArgs(args, call.argc);
call.callData = callDataStart();
- call.result = getResultParam(result);
+ call.result = getResultParam(target);
addInstruction(call);
return;
}
@@ -528,11 +528,11 @@ void InstructionSelection::constructActivationProperty(IR::Name *func,
create.name = registerString(*func->id);
prepareCallArgs(args, create.argc);
create.callData = callDataStart();
- create.result = getResultParam(result);
+ create.result = getResultParam(target);
addInstruction(create);
}
-void InstructionSelection::constructProperty(IR::Temp *base, const QString &name, IR::ExprList *args, IR::Temp *result)
+void InstructionSelection::constructProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *target)
{
if (useFastLookups) {
Instruction::ConstructPropertyLookup call;
@@ -540,7 +540,7 @@ void InstructionSelection::constructProperty(IR::Temp *base, const QString &name
call.index = registerGetterLookup(name);
prepareCallArgs(args, call.argc);
call.callData = callDataStart();
- call.result = getResultParam(result);
+ call.result = getResultParam(target);
addInstruction(call);
return;
}
@@ -549,101 +549,101 @@ void InstructionSelection::constructProperty(IR::Temp *base, const QString &name
create.name = registerString(name);
prepareCallArgs(args, create.argc);
create.callData = callDataStart();
- create.result = getResultParam(result);
+ create.result = getResultParam(target);
addInstruction(create);
}
-void InstructionSelection::constructValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result)
+void InstructionSelection::constructValue(IR::Expr *value, IR::ExprList *args, IR::Expr *target)
{
Instruction::CreateValue create;
create.func = getParam(value);
prepareCallArgs(args, create.argc);
create.callData = callDataStart();
- create.result = getResultParam(result);
+ create.result = getResultParam(target);
addInstruction(create);
}
-void InstructionSelection::loadThisObject(IR::Temp *temp)
+void InstructionSelection::loadThisObject(IR::Expr *e)
{
Instruction::LoadThis load;
- load.result = getResultParam(temp);
+ load.result = getResultParam(e);
addInstruction(load);
}
-void InstructionSelection::loadQmlIdArray(IR::Temp *temp)
+void InstructionSelection::loadQmlIdArray(IR::Expr *e)
{
Instruction::LoadQmlIdArray load;
- load.result = getResultParam(temp);
+ load.result = getResultParam(e);
addInstruction(load);
}
-void InstructionSelection::loadQmlImportedScripts(IR::Temp *temp)
+void InstructionSelection::loadQmlImportedScripts(IR::Expr *e)
{
Instruction::LoadQmlImportedScripts load;
- load.result = getResultParam(temp);
+ load.result = getResultParam(e);
addInstruction(load);
}
-void InstructionSelection::loadQmlContextObject(IR::Temp *temp)
+void InstructionSelection::loadQmlContextObject(IR::Expr *e)
{
Instruction::LoadQmlContextObject load;
- load.result = getResultParam(temp);
+ load.result = getResultParam(e);
addInstruction(load);
}
-void InstructionSelection::loadQmlScopeObject(IR::Temp *temp)
+void InstructionSelection::loadQmlScopeObject(IR::Expr *e)
{
Instruction::LoadQmlScopeObject load;
- load.result = getResultParam(temp);
+ load.result = getResultParam(e);
addInstruction(load);
}
-void InstructionSelection::loadQmlSingleton(const QString &name, IR::Temp *temp)
+void InstructionSelection::loadQmlSingleton(const QString &name, IR::Expr *e)
{
Instruction::LoadQmlSingleton load;
- load.result = getResultParam(temp);
+ load.result = getResultParam(e);
load.name = registerString(name);
addInstruction(load);
}
-void InstructionSelection::loadConst(IR::Const *sourceConst, IR::Temp *targetTemp)
+void InstructionSelection::loadConst(IR::Const *sourceConst, IR::Expr *e)
{
Q_ASSERT(sourceConst);
Instruction::MoveConst move;
move.source = convertToValue(sourceConst).asReturnedValue();
- move.result = getResultParam(targetTemp);
+ move.result = getResultParam(e);
addInstruction(move);
}
-void InstructionSelection::loadString(const QString &str, IR::Temp *targetTemp)
+void InstructionSelection::loadString(const QString &str, IR::Expr *target)
{
Instruction::LoadRuntimeString load;
load.stringId = registerString(str);
- load.result = getResultParam(targetTemp);
+ load.result = getResultParam(target);
addInstruction(load);
}
-void InstructionSelection::loadRegexp(IR::RegExp *sourceRegexp, IR::Temp *targetTemp)
+void InstructionSelection::loadRegexp(IR::RegExp *sourceRegexp, IR::Expr *target)
{
Instruction::LoadRegExp load;
load.regExpId = registerRegExp(sourceRegexp);
- load.result = getResultParam(targetTemp);
+ load.result = getResultParam(target);
addInstruction(load);
}
-void InstructionSelection::getActivationProperty(const IR::Name *name, IR::Temp *temp)
+void InstructionSelection::getActivationProperty(const IR::Name *name, IR::Expr *target)
{
if (useFastLookups && name->global) {
Instruction::GetGlobalLookup load;
load.index = registerGlobalGetterLookup(*name->id);
- load.result = getResultParam(temp);
+ load.result = getResultParam(target);
addInstruction(load);
return;
}
Instruction::LoadName load;
load.name = registerString(*name->id);
- load.result = getResultParam(temp);
+ load.result = getResultParam(target);
addInstruction(load);
}
@@ -655,7 +655,7 @@ void InstructionSelection::setActivationProperty(IR::Expr *source, const QString
addInstruction(store);
}
-void InstructionSelection::initClosure(IR::Closure *closure, IR::Temp *target)
+void InstructionSelection::initClosure(IR::Closure *closure, IR::Expr *target)
{
int id = closure->value;
Instruction::LoadClosure load;
@@ -664,7 +664,7 @@ void InstructionSelection::initClosure(IR::Closure *closure, IR::Temp *target)
addInstruction(load);
}
-void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR::Temp *target)
+void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR::Expr *target)
{
if (useFastLookups) {
Instruction::GetLookup load;
@@ -708,7 +708,7 @@ void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *target
addInstruction(store);
}
-void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Temp *target)
+void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Expr *target)
{
if (attachedPropertiesId != 0) {
Instruction::LoadAttachedQObjectProperty load;
@@ -726,7 +726,7 @@ void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex,
}
}
-void InstructionSelection::getElement(IR::Expr *base, IR::Expr *index, IR::Temp *target)
+void InstructionSelection::getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target)
{
if (useFastLookups) {
Instruction::LoadElementLookup load;
@@ -763,92 +763,92 @@ void InstructionSelection::setElement(IR::Expr *source, IR::Expr *targetBase,
addInstruction(store);
}
-void InstructionSelection::copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp)
+void InstructionSelection::copyValue(IR::Expr *source, IR::Expr *target)
{
Instruction::Move move;
- move.source = getParam(sourceTemp);
- move.result = getResultParam(targetTemp);
+ move.source = getParam(source);
+ move.result = getResultParam(target);
if (move.source != move.result)
addInstruction(move);
}
-void InstructionSelection::swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp)
+void InstructionSelection::swapValues(IR::Expr *source, IR::Expr *target)
{
Instruction::SwapTemps swap;
- swap.left = getParam(sourceTemp);
- swap.right = getParam(targetTemp);
+ swap.left = getParam(source);
+ swap.right = getParam(target);
addInstruction(swap);
}
-void InstructionSelection::unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *targetTemp)
+void InstructionSelection::unop(IR::AluOp oper, IR::Expr *source, IR::Expr *target)
{
switch (oper) {
case IR::OpIfTrue:
Q_ASSERT(!"unreachable"); break;
case IR::OpNot: {
// ### enabling this fails in some cases, where apparently the value is not a bool at runtime
- if (0 && isBoolType(sourceTemp)) {
+ if (0 && isBoolType(source)) {
Instruction::UNotBool unot;
- unot.source = getParam(sourceTemp);
- unot.result = getResultParam(targetTemp);
+ unot.source = getParam(source);
+ unot.result = getResultParam(target);
addInstruction(unot);
return;
}
Instruction::UNot unot;
- unot.source = getParam(sourceTemp);
- unot.result = getResultParam(targetTemp);
+ unot.source = getParam(source);
+ unot.result = getResultParam(target);
addInstruction(unot);
return;
}
case IR::OpUMinus: {
Instruction::UMinus uminus;
- uminus.source = getParam(sourceTemp);
- uminus.result = getResultParam(targetTemp);
+ uminus.source = getParam(source);
+ uminus.result = getResultParam(target);
addInstruction(uminus);
return;
}
case IR::OpUPlus: {
- if (isNumberType(sourceTemp)) {
+ if (isNumberType(source)) {
// use a move
Instruction::Move move;
- move.source = getParam(sourceTemp);
- move.result = getResultParam(targetTemp);
+ move.source = getParam(source);
+ move.result = getResultParam(target);
if (move.source != move.result)
addInstruction(move);
return;
}
Instruction::UPlus uplus;
- uplus.source = getParam(sourceTemp);
- uplus.result = getResultParam(targetTemp);
+ uplus.source = getParam(source);
+ uplus.result = getResultParam(target);
addInstruction(uplus);
return;
}
case IR::OpCompl: {
// ### enabling this fails in some cases, where apparently the value is not a int at runtime
- if (0 && isIntegerType(sourceTemp)) {
+ if (0 && isIntegerType(source)) {
Instruction::UComplInt unot;
- unot.source = getParam(sourceTemp);
- unot.result = getResultParam(targetTemp);
+ unot.source = getParam(source);
+ unot.result = getResultParam(target);
addInstruction(unot);
return;
}
Instruction::UCompl ucompl;
- ucompl.source = getParam(sourceTemp);
- ucompl.result = getResultParam(targetTemp);
+ ucompl.source = getParam(source);
+ ucompl.result = getResultParam(target);
addInstruction(ucompl);
return;
}
case IR::OpIncrement: {
Instruction::Increment inc;
- inc.source = getParam(sourceTemp);
- inc.result = getResultParam(targetTemp);
+ inc.source = getParam(source);
+ inc.result = getResultParam(target);
addInstruction(inc);
return;
}
case IR::OpDecrement: {
Instruction::Decrement dec;
- dec.source = getParam(sourceTemp);
- dec.result = getResultParam(targetTemp);
+ dec.source = getParam(source);
+ dec.result = getResultParam(target);
addInstruction(dec);
return;
}
@@ -858,12 +858,12 @@ void InstructionSelection::unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *
Q_ASSERT(!"unreachable");
}
-void InstructionSelection::binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target)
+void InstructionSelection::binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target)
{
binopHelper(oper, leftSource, rightSource, target);
}
-Param InstructionSelection::binopHelper(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target)
+Param InstructionSelection::binopHelper(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target)
{
if (oper == IR::OpAdd) {
Instruction::Add add;
@@ -1103,7 +1103,7 @@ void InstructionSelection::visitRet(IR::Ret *s)
addInstruction(ret);
}
-void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Temp *result)
+void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result)
{
if (useFastLookups && func->global) {
Instruction::CallGlobalLookup call;
@@ -1123,7 +1123,7 @@ void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args
}
void InstructionSelection::callBuiltinTypeofMember(IR::Expr *base, const QString &name,
- IR::Temp *result)
+ IR::Expr *result)
{
Instruction::CallBuiltinTypeofMember call;
call.base = getParam(base);
@@ -1133,7 +1133,7 @@ void InstructionSelection::callBuiltinTypeofMember(IR::Expr *base, const QString
}
void InstructionSelection::callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index,
- IR::Temp *result)
+ IR::Expr *result)
{
Instruction::CallBuiltinTypeofSubscript call;
call.base = getParam(base);
@@ -1142,7 +1142,7 @@ void InstructionSelection::callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *
addInstruction(call);
}
-void InstructionSelection::callBuiltinTypeofName(const QString &name, IR::Temp *result)
+void InstructionSelection::callBuiltinTypeofName(const QString &name, IR::Expr *result)
{
Instruction::CallBuiltinTypeofName call;
call.name = registerString(name);
@@ -1150,7 +1150,7 @@ void InstructionSelection::callBuiltinTypeofName(const QString &name, IR::Temp *
addInstruction(call);
}
-void InstructionSelection::callBuiltinTypeofValue(IR::Expr *value, IR::Temp *result)
+void InstructionSelection::callBuiltinTypeofValue(IR::Expr *value, IR::Expr *result)
{
Instruction::CallBuiltinTypeofValue call;
call.value = getParam(value);
@@ -1158,7 +1158,7 @@ void InstructionSelection::callBuiltinTypeofValue(IR::Expr *value, IR::Temp *res
addInstruction(call);
}
-void InstructionSelection::callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result)
+void InstructionSelection::callBuiltinDeleteMember(IR::Expr *base, const QString &name, IR::Expr *result)
{
Instruction::CallBuiltinDeleteMember call;
call.base = getParam(base);
@@ -1167,8 +1167,8 @@ void InstructionSelection::callBuiltinDeleteMember(IR::Temp *base, const QString
addInstruction(call);
}
-void InstructionSelection::callBuiltinDeleteSubscript(IR::Temp *base, IR::Expr *index,
- IR::Temp *result)
+void InstructionSelection::callBuiltinDeleteSubscript(IR::Expr *base, IR::Expr *index,
+ IR::Expr *result)
{
Instruction::CallBuiltinDeleteSubscript call;
call.base = getParam(base);
@@ -1177,7 +1177,7 @@ void InstructionSelection::callBuiltinDeleteSubscript(IR::Temp *base, IR::Expr *
addInstruction(call);
}
-void InstructionSelection::callBuiltinDeleteName(const QString &name, IR::Temp *result)
+void InstructionSelection::callBuiltinDeleteName(const QString &name, IR::Expr *result)
{
Instruction::CallBuiltinDeleteName call;
call.name = registerString(name);
@@ -1185,7 +1185,7 @@ void InstructionSelection::callBuiltinDeleteName(const QString &name, IR::Temp *
addInstruction(call);
}
-void InstructionSelection::callBuiltinDeleteValue(IR::Temp *result)
+void InstructionSelection::callBuiltinDeleteValue(IR::Expr *result)
{
Instruction::MoveConst move;
move.source = QV4::Encode(false);
@@ -1217,7 +1217,7 @@ void InstructionSelection::callBuiltinReThrow()
}
}
-void InstructionSelection::callBuiltinUnwindException(IR::Temp *result)
+void InstructionSelection::callBuiltinUnwindException(IR::Expr *result)
{
Instruction::CallBuiltinUnwindException call;
call.result = getResultParam(result);
@@ -1232,7 +1232,7 @@ void InstructionSelection::callBuiltinPushCatchScope(const QString &exceptionNam
addInstruction(call);
}
-void InstructionSelection::callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Temp *result)
+void InstructionSelection::callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Expr *result)
{
Instruction::CallBuiltinForeachIteratorObject call;
call.arg = getParam(arg);
@@ -1240,7 +1240,7 @@ void InstructionSelection::callBuiltinForeachIteratorObject(IR::Expr *arg, IR::T
addInstruction(call);
}
-void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result)
+void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Expr *arg, IR::Expr *result)
{
Instruction::CallBuiltinForeachNextPropertyName call;
call.arg = getParam(arg);
@@ -1248,7 +1248,7 @@ void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Temp *arg, IR:
addInstruction(call);
}
-void InstructionSelection::callBuiltinPushWithScope(IR::Temp *arg)
+void InstructionSelection::callBuiltinPushWithScope(IR::Expr *arg)
{
Instruction::CallBuiltinPushScope call;
call.arg = getParam(arg);
@@ -1269,7 +1269,7 @@ void InstructionSelection::callBuiltinDeclareVar(bool deletable, const QString &
addInstruction(call);
}
-void InstructionSelection::callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args)
+void InstructionSelection::callBuiltinDefineArray(IR::Expr *result, IR::ExprList *args)
{
Instruction::CallBuiltinDefineArray call;
prepareCallArgs(args, call.argc, &call.args);
@@ -1277,7 +1277,7 @@ void InstructionSelection::callBuiltinDefineArray(IR::Temp *result, IR::ExprList
addInstruction(call);
}
-void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray)
+void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Expr *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray)
{
int argLocation = outgoingArgumentTempStart();
@@ -1397,7 +1397,7 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, int
addInstruction(call);
}
-void InstructionSelection::callBuiltinSetupArgumentObject(IR::Temp *result)
+void InstructionSelection::callBuiltinSetupArgumentObject(IR::Expr *result)
{
Instruction::CallBuiltinSetupArgumentsObject call;
call.result = getResultParam(result);
@@ -1475,16 +1475,22 @@ Param InstructionSelection::getParam(IR::Expr *e) {
return Param::createConstant(idx);
} else if (IR::Temp *t = e->asTemp()) {
switch (t->kind) {
- case IR::Temp::Formal:
- case IR::Temp::ScopedFormal: return Param::createArgument(t->index, t->scope);
- case IR::Temp::Local: return Param::createLocal(t->index);
- case IR::Temp::ScopedLocal: return Param::createScopedLocal(t->index, t->scope);
case IR::Temp::StackSlot:
return Param::createTemp(t->index);
default:
Q_UNREACHABLE();
return Param();
}
+ } else if (IR::ArgLocal *al = e->asArgLocal()) {
+ switch (al->kind) {
+ case IR::ArgLocal::Formal:
+ case IR::ArgLocal::ScopedFormal: return Param::createArgument(al->index, al->scope);
+ case IR::ArgLocal::Local: return Param::createLocal(al->index);
+ case IR::ArgLocal::ScopedLocal: return Param::createScopedLocal(al->index, al->scope);
+ default:
+ Q_UNREACHABLE();
+ return Param();
+ }
} else {
Q_UNIMPLEMENTED();
return Param();
diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h
index 0aa1972fb4..6f9f001f28 100644
--- a/src/qml/compiler/qv4isel_moth_p.h
+++ b/src/qml/compiler/qv4isel_moth_p.h
@@ -80,60 +80,60 @@ protected:
virtual void visitCJump(IR::CJump *);
virtual void visitRet(IR::Ret *);
- virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Temp *result);
- virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Temp *result);
- virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Temp *result);
- virtual void callBuiltinTypeofName(const QString &name, IR::Temp *result);
- virtual void callBuiltinTypeofValue(IR::Expr *value, IR::Temp *result);
- virtual void callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result);
- virtual void callBuiltinDeleteSubscript(IR::Temp *base, IR::Expr *index, IR::Temp *result);
- virtual void callBuiltinDeleteName(const QString &name, IR::Temp *result);
- virtual void callBuiltinDeleteValue(IR::Temp *result);
+ virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result);
+ virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Expr *result);
+ virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Expr *result);
+ virtual void callBuiltinTypeofName(const QString &name, IR::Expr *result);
+ virtual void callBuiltinTypeofValue(IR::Expr *value, IR::Expr *result);
+ virtual void callBuiltinDeleteMember(IR::Expr *base, const QString &name, IR::Expr *result);
+ virtual void callBuiltinDeleteSubscript(IR::Expr *base, IR::Expr *index, IR::Expr *result);
+ virtual void callBuiltinDeleteName(const QString &name, IR::Expr *result);
+ virtual void callBuiltinDeleteValue(IR::Expr *result);
virtual void callBuiltinThrow(IR::Expr *arg);
virtual void callBuiltinReThrow();
- virtual void callBuiltinUnwindException(IR::Temp *);
+ virtual void callBuiltinUnwindException(IR::Expr *);
virtual void callBuiltinPushCatchScope(const QString &exceptionName);
- virtual void callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Temp *result);
- virtual void callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result);
- virtual void callBuiltinPushWithScope(IR::Temp *arg);
+ virtual void callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Expr *result);
+ virtual void callBuiltinForeachNextPropertyname(IR::Expr *arg, IR::Expr *result);
+ virtual void callBuiltinPushWithScope(IR::Expr *arg);
virtual void callBuiltinPopScope();
virtual void callBuiltinDeclareVar(bool deletable, const QString &name);
- virtual void callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args);
- virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray);
- virtual void callBuiltinSetupArgumentObject(IR::Temp *result);
+ virtual void callBuiltinDefineArray(IR::Expr *result, IR::ExprList *args);
+ virtual void callBuiltinDefineObjectLiteral(IR::Expr *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray);
+ virtual void callBuiltinSetupArgumentObject(IR::Expr *result);
virtual void callBuiltinConvertThisToObject();
- virtual void callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result);
- virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Temp *result);
- virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Temp *result);
- virtual void convertType(IR::Temp *source, IR::Temp *target);
- virtual void constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Temp *result);
- virtual void constructProperty(IR::Temp *base, const QString &name, IR::ExprList *args, IR::Temp *result);
- virtual void constructValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result);
- virtual void loadThisObject(IR::Temp *temp);
- virtual void loadQmlIdArray(IR::Temp *temp);
- virtual void loadQmlImportedScripts(IR::Temp *temp);
- virtual void loadQmlContextObject(IR::Temp *temp);
- virtual void loadQmlScopeObject(IR::Temp *temp);
- virtual void loadQmlSingleton(const QString &name, IR::Temp *temp);
- virtual void loadConst(IR::Const *sourceConst, IR::Temp *targetTemp);
- virtual void loadString(const QString &str, IR::Temp *targetTemp);
- virtual void loadRegexp(IR::RegExp *sourceRegexp, IR::Temp *targetTemp);
- virtual void getActivationProperty(const IR::Name *name, IR::Temp *temp);
+ virtual void callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result);
+ virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result);
+ virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Expr *result);
+ virtual void convertType(IR::Expr *source, IR::Expr *target);
+ virtual void constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Expr *result);
+ virtual void constructProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result);
+ virtual void constructValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result);
+ virtual void loadThisObject(IR::Expr *e);
+ virtual void loadQmlIdArray(IR::Expr *e);
+ virtual void loadQmlImportedScripts(IR::Expr *e);
+ virtual void loadQmlContextObject(IR::Expr *e);
+ virtual void loadQmlScopeObject(IR::Expr *e);
+ virtual void loadQmlSingleton(const QString &name, IR::Expr *e);
+ virtual void loadConst(IR::Const *sourceConst, IR::Expr *e);
+ virtual void loadString(const QString &str, IR::Expr *target);
+ virtual void loadRegexp(IR::RegExp *sourceRegexp, IR::Expr *target);
+ virtual void getActivationProperty(const IR::Name *name, IR::Expr *target);
virtual void setActivationProperty(IR::Expr *source, const QString &targetName);
- virtual void initClosure(IR::Closure *closure, IR::Temp *target);
- virtual void getProperty(IR::Expr *base, const QString &name, IR::Temp *target);
+ virtual void initClosure(IR::Closure *closure, IR::Expr *target);
+ virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target);
virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName);
virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex);
- virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Temp *target);
- virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Temp *target);
+ virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Expr *target);
+ virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target);
virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex);
- virtual void copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp);
- virtual void swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp);
- virtual void unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *targetTemp);
- virtual void binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target);
+ virtual void copyValue(IR::Expr *source, IR::Expr *target);
+ virtual void swapValues(IR::Expr *source, IR::Expr *target);
+ virtual void unop(IR::AluOp oper, IR::Expr *source, IR::Expr *target);
+ virtual void binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target);
private:
- Param binopHelper(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target);
+ Param binopHelper(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target);
struct Instruction {
#define MOTH_INSTR_DATA_TYPEDEF(I, FMT) typedef InstrData<Instr::I> I;
@@ -145,7 +145,7 @@ private:
Param getParam(IR::Expr *e);
- Param getResultParam(IR::Temp *result)
+ Param getResultParam(IR::Expr *result)
{
if (result)
return getParam(result);
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index c055cffd0d..f5cb1905c5 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -93,54 +93,54 @@ QV4::CompiledData::CompilationUnit *EvalInstructionSelection::compile(bool gener
void IRDecoder::visitMove(IR::Move *s)
{
if (IR::Name *n = s->target->asName()) {
- if (s->source->asTemp() || s->source->asConst()) {
+ if (s->source->asTemp() || s->source->asConst() || s->source->asArgLocal()) {
setActivationProperty(s->source, *n->id);
return;
}
- } else if (IR::Temp *t = s->target->asTemp()) {
+ } else if (s->target->asTemp() || s->target->asArgLocal()) {
if (IR::Name *n = s->source->asName()) {
if (n->id && *n->id == QStringLiteral("this")) // TODO: `this' should be a builtin.
- loadThisObject(t);
+ loadThisObject(s->target);
else if (n->builtin == IR::Name::builtin_qml_id_array)
- loadQmlIdArray(t);
+ loadQmlIdArray(s->target);
else if (n->builtin == IR::Name::builtin_qml_context_object)
- loadQmlContextObject(t);
+ loadQmlContextObject(s->target);
else if (n->builtin == IR::Name::builtin_qml_scope_object)
- loadQmlScopeObject(t);
+ loadQmlScopeObject(s->target);
else if (n->builtin == IR::Name::builtin_qml_imported_scripts_object)
- loadQmlImportedScripts(t);
+ loadQmlImportedScripts(s->target);
else if (n->qmlSingleton)
- loadQmlSingleton(*n->id, t);
+ loadQmlSingleton(*n->id, s->target);
else
- getActivationProperty(n, t);
+ getActivationProperty(n, s->target);
return;
} else if (IR::Const *c = s->source->asConst()) {
- loadConst(c, t);
+ loadConst(c, s->target);
return;
- } else if (IR::Temp *t2 = s->source->asTemp()) {
+ } else if (s->source->asTemp() || s->source->asArgLocal()) {
if (s->swap)
- swapValues(t2, t);
+ swapValues(s->source, s->target);
else
- copyValue(t2, t);
+ copyValue(s->source, s->target);
return;
} else if (IR::String *str = s->source->asString()) {
- loadString(*str->value, t);
+ loadString(*str->value, s->target);
return;
} else if (IR::RegExp *re = s->source->asRegExp()) {
- loadRegexp(re, t);
+ loadRegexp(re, s->target);
return;
} else if (IR::Closure *clos = s->source->asClosure()) {
- initClosure(clos, t);
+ initClosure(clos, s->target);
return;
} else if (IR::New *ctor = s->source->asNew()) {
if (Name *func = ctor->base->asName()) {
- constructActivationProperty(func, ctor->args, t);
+ constructActivationProperty(func, ctor->args, s->target);
return;
} else if (IR::Member *member = ctor->base->asMember()) {
- constructProperty(member->base->asTemp(), *member->name, ctor->args, t);
+ constructProperty(member->base, *member->name, ctor->args, s->target);
return;
- } else if (IR::Temp *value = ctor->base->asTemp()) {
- constructValue(value, ctor->args, t);
+ } else if (ctor->base->asTemp() || ctor->base->asArgLocal()) {
+ constructValue(ctor->base, ctor->args, s->target);
return;
}
} else if (IR::Member *m = s->source->asMember()) {
@@ -162,46 +162,44 @@ void IRDecoder::visitMove(IR::Move *s)
captureRequired = false;
}
}
- getQObjectProperty(m->base, m->property->coreIndex, captureRequired, attachedPropertiesId, t);
+ getQObjectProperty(m->base, m->property->coreIndex, captureRequired, attachedPropertiesId, s->target);
#endif // V4_BOOTSTRAP
return;
- } else if (m->base->asTemp() || m->base->asConst()) {
- getProperty(m->base, *m->name, t);
+ } else if (m->base->asTemp() || m->base->asConst() || m->base->asArgLocal()) {
+ getProperty(m->base, *m->name, s->target);
return;
}
} else if (IR::Subscript *ss = s->source->asSubscript()) {
- getElement(ss->base, ss->index, t);
+ getElement(ss->base, ss->index, s->target);
return;
} else if (IR::Unop *u = s->source->asUnop()) {
- if (IR::Temp *e = u->expr->asTemp()) {
- unop(u->op, e, t);
- return;
- }
+ unop(u->op, u->expr, s->target);
+ return;
} else if (IR::Binop *b = s->source->asBinop()) {
- binop(b->op, b->left, b->right, t);
+ binop(b->op, b->left, b->right, s->target);
return;
} else if (IR::Call *c = s->source->asCall()) {
if (c->base->asName()) {
- callBuiltin(c, t);
+ callBuiltin(c, s->target);
return;
} else if (Member *member = c->base->asMember()) {
- callProperty(member->base, *member->name, c->args, t);
+ callProperty(member->base, *member->name, c->args, s->target);
return;
} else if (Subscript *ss = c->base->asSubscript()) {
- callSubscript(ss->base, ss->index, c->args, t);
+ callSubscript(ss->base, ss->index, c->args, s->target);
return;
- } else if (IR::Temp *value = c->base->asTemp()) {
- callValue(value, c->args, t);
+ } else if (c->base->asTemp() || c->base->asArgLocal()) {
+ callValue(c->base, c->args, s->target);
return;
}
} else if (IR::Convert *c = s->source->asConvert()) {
- Q_ASSERT(c->expr->asTemp());
- convertType(c->expr->asTemp(), t);
+ Q_ASSERT(c->expr->asTemp() || c->expr->asArgLocal());
+ convertType(c->expr, s->target);
return;
}
} else if (IR::Member *m = s->target->asMember()) {
- if (m->base->asTemp() || m->base->asConst()) {
- if (s->source->asTemp() || s->source->asConst()) {
+ if (m->base->asTemp() || m->base->asConst() || m->base->asArgLocal()) {
+ if (s->source->asTemp() || s->source->asConst() || s->source->asArgLocal()) {
Q_ASSERT(m->kind != IR::Member::MemberOfEnum);
const int attachedPropertiesId = m->attachedPropertiesIdOrEnumValue;
if (m->property && attachedPropertiesId == 0) {
@@ -218,7 +216,7 @@ void IRDecoder::visitMove(IR::Move *s)
}
}
} else if (IR::Subscript *ss = s->target->asSubscript()) {
- if (s->source->asTemp() || s->source->asConst()) {
+ if (s->source->asTemp() || s->source->asConst() || s->source->asArgLocal()) {
setElement(s->source, ss->base, ss->index);
return;
}
@@ -241,11 +239,11 @@ void IRDecoder::visitExp(IR::Exp *s)
// These are calls where the result is ignored.
if (c->base->asName()) {
callBuiltin(c, 0);
- } else if (Temp *value = c->base->asTemp()) {
- callValue(value, c->args, 0);
+ } else if (c->base->asTemp() || c->base->asArgLocal()) {
+ callValue(c->base, c->args, 0);
} else if (Member *member = c->base->asMember()) {
- Q_ASSERT(member->base->asTemp());
- callProperty(member->base->asTemp(), *member->name, c->args, 0);
+ Q_ASSERT(member->base->asTemp() || member->base->asArgLocal());
+ callProperty(member->base, *member->name, c->args, 0);
} else if (Subscript *s = c->base->asSubscript()) {
callSubscript(s->base, s->index, c->args, 0);
} else {
@@ -256,7 +254,7 @@ void IRDecoder::visitExp(IR::Exp *s)
}
}
-void IRDecoder::callBuiltin(IR::Call *call, IR::Temp *result)
+void IRDecoder::callBuiltin(IR::Call *call, Expr *result)
{
IR::Name *baseName = call->base->asName();
Q_ASSERT(baseName != 0);
@@ -276,7 +274,9 @@ void IRDecoder::callBuiltin(IR::Call *call, IR::Temp *result)
} else if (IR::Name *n = call->args->expr->asName()) {
callBuiltinTypeofName(*n->id, result);
return;
- } else if (call->args->expr->asTemp() || call->args->expr->asConst()){
+ } else if (call->args->expr->asTemp() ||
+ call->args->expr->asConst() ||
+ call->args->expr->asArgLocal()) {
callBuiltinTypeofValue(call->args->expr, result);
return;
}
@@ -284,15 +284,16 @@ void IRDecoder::callBuiltin(IR::Call *call, IR::Temp *result)
case IR::Name::builtin_delete: {
if (IR::Member *m = call->args->expr->asMember()) {
- callBuiltinDeleteMember(m->base->asTemp(), *m->name, result);
+ callBuiltinDeleteMember(m->base, *m->name, result);
return;
} else if (IR::Subscript *ss = call->args->expr->asSubscript()) {
- callBuiltinDeleteSubscript(ss->base->asTemp(), ss->index, result);
+ callBuiltinDeleteSubscript(ss->base, ss->index, result);
return;
} else if (IR::Name *n = call->args->expr->asName()) {
callBuiltinDeleteName(*n->id, result);
return;
- } else if (call->args->expr->asTemp()){
+ } else if (call->args->expr->asTemp() ||
+ call->args->expr->asArgLocal()) {
// TODO: should throw in strict mode
callBuiltinDeleteValue(result);
return;
@@ -301,7 +302,7 @@ void IRDecoder::callBuiltin(IR::Call *call, IR::Temp *result)
case IR::Name::builtin_throw: {
IR::Expr *arg = call->args->expr;
- Q_ASSERT(arg->asTemp() || arg->asConst());
+ Q_ASSERT(arg->asTemp() || arg->asConst() || arg->asArgLocal());
callBuiltinThrow(arg);
} return;
@@ -326,14 +327,15 @@ void IRDecoder::callBuiltin(IR::Call *call, IR::Temp *result)
} return;
case IR::Name::builtin_foreach_next_property_name: {
- IR::Temp *arg = call->args->expr->asTemp();
+ IR::Expr *arg = call->args->expr;
Q_ASSERT(arg != 0);
callBuiltinForeachNextPropertyname(arg, result);
} return;
case IR::Name::builtin_push_with_scope: {
- IR::Temp *arg = call->args->expr->asTemp();
- Q_ASSERT(arg != 0);
- callBuiltinPushWithScope(arg);
+ if (call->args->expr->asTemp() || call->args->expr->asArgLocal())
+ callBuiltinPushWithScope(call->args->expr);
+ else
+ Q_UNIMPLEMENTED();
} return;
case IR::Name::builtin_pop_scope:
diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h
index 74e6ba8200..cbfc21c211 100644
--- a/src/qml/compiler/qv4isel_p.h
+++ b/src/qml/compiler/qv4isel_p.h
@@ -112,60 +112,60 @@ public: // visitor methods for StmtVisitor:
virtual void visitExp(IR::Exp *s);
public: // to implement by subclasses:
- virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Temp *result) = 0;
- virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Temp *result) = 0;
- virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Temp *result) = 0;
- virtual void callBuiltinTypeofName(const QString &name, IR::Temp *result) = 0;
- virtual void callBuiltinTypeofValue(IR::Expr *value, IR::Temp *result) = 0;
- virtual void callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result) = 0;
- virtual void callBuiltinDeleteSubscript(IR::Temp *base, IR::Expr *index, IR::Temp *result) = 0;
- virtual void callBuiltinDeleteName(const QString &name, IR::Temp *result) = 0;
- virtual void callBuiltinDeleteValue(IR::Temp *result) = 0;
+ virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result) = 0;
+ virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Expr *result) = 0;
+ virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Expr *result) = 0;
+ virtual void callBuiltinTypeofName(const QString &name, IR::Expr *result) = 0;
+ virtual void callBuiltinTypeofValue(IR::Expr *value, IR::Expr *result) = 0;
+ virtual void callBuiltinDeleteMember(IR::Expr *base, const QString &name, IR::Expr *result) = 0;
+ virtual void callBuiltinDeleteSubscript(IR::Expr *base, IR::Expr *index, IR::Expr *result) = 0;
+ virtual void callBuiltinDeleteName(const QString &name, IR::Expr *result) = 0;
+ virtual void callBuiltinDeleteValue(IR::Expr *result) = 0;
virtual void callBuiltinThrow(IR::Expr *arg) = 0;
virtual void callBuiltinReThrow() = 0;
- virtual void callBuiltinUnwindException(IR::Temp *) = 0;
+ virtual void callBuiltinUnwindException(IR::Expr *) = 0;
virtual void callBuiltinPushCatchScope(const QString &exceptionName) = 0;
- virtual void callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Temp *result) = 0;
- virtual void callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result) = 0;
- virtual void callBuiltinPushWithScope(IR::Temp *arg) = 0;
+ virtual void callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Expr *result) = 0;
+ virtual void callBuiltinForeachNextPropertyname(IR::Expr *arg, IR::Expr *result) = 0;
+ virtual void callBuiltinPushWithScope(IR::Expr *arg) = 0;
virtual void callBuiltinPopScope() = 0;
virtual void callBuiltinDeclareVar(bool deletable, const QString &name) = 0;
- virtual void callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args) = 0;
- virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray) = 0;
- virtual void callBuiltinSetupArgumentObject(IR::Temp *result) = 0;
+ virtual void callBuiltinDefineArray(IR::Expr *result, IR::ExprList *args) = 0;
+ virtual void callBuiltinDefineObjectLiteral(IR::Expr *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray) = 0;
+ virtual void callBuiltinSetupArgumentObject(IR::Expr *result) = 0;
virtual void callBuiltinConvertThisToObject() = 0;
- virtual void callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result) = 0;
- virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Temp *result) = 0;
- virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Temp *result) = 0;
- virtual void convertType(IR::Temp *source, IR::Temp *target) = 0;
- virtual void constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Temp *result) = 0;
- virtual void constructProperty(IR::Temp *base, const QString &name, IR::ExprList *args, IR::Temp *result) = 0;
- virtual void constructValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result) = 0;
- virtual void loadThisObject(IR::Temp *temp) = 0;
- virtual void loadQmlIdArray(IR::Temp *temp) = 0;
- virtual void loadQmlImportedScripts(IR::Temp *temp) = 0;
- virtual void loadQmlContextObject(IR::Temp *temp) = 0;
- virtual void loadQmlScopeObject(IR::Temp *temp) = 0;
- virtual void loadQmlSingleton(const QString &name, IR::Temp *temp) = 0;
- virtual void loadConst(IR::Const *sourceConst, IR::Temp *targetTemp) = 0;
- virtual void loadString(const QString &str, IR::Temp *targetTemp) = 0;
- virtual void loadRegexp(IR::RegExp *sourceRegexp, IR::Temp *targetTemp) = 0;
- virtual void getActivationProperty(const IR::Name *name, IR::Temp *temp) = 0;
+ virtual void callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result) = 0;
+ virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result) = 0;
+ virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Expr *result) = 0;
+ virtual void convertType(IR::Expr *source, IR::Expr *target) = 0;
+ virtual void constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Expr *result) = 0;
+ virtual void constructProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result) = 0;
+ virtual void constructValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result) = 0;
+ virtual void loadThisObject(IR::Expr *target) = 0;
+ virtual void loadQmlIdArray(IR::Expr *target) = 0;
+ virtual void loadQmlImportedScripts(IR::Expr *target) = 0;
+ virtual void loadQmlContextObject(IR::Expr *target) = 0;
+ virtual void loadQmlScopeObject(IR::Expr *target) = 0;
+ virtual void loadQmlSingleton(const QString &name, IR::Expr *target) = 0;
+ virtual void loadConst(IR::Const *sourceConst, IR::Expr *target) = 0;
+ virtual void loadString(const QString &str, IR::Expr *target) = 0;
+ virtual void loadRegexp(IR::RegExp *sourceRegexp, IR::Expr *target) = 0;
+ virtual void getActivationProperty(const IR::Name *name, IR::Expr *target) = 0;
virtual void setActivationProperty(IR::Expr *source, const QString &targetName) = 0;
- virtual void initClosure(IR::Closure *closure, IR::Temp *target) = 0;
- virtual void getProperty(IR::Expr *base, const QString &name, IR::Temp *target) = 0;
- virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Temp *targetTemp) = 0;
+ virtual void initClosure(IR::Closure *closure, IR::Expr *target) = 0;
+ virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target) = 0;
+ virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Expr *target) = 0;
virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName) = 0;
virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex) = 0;
- virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Temp *target) = 0;
+ virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target) = 0;
virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex) = 0;
- virtual void copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp) = 0;
- virtual void swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp) = 0;
- virtual void unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *targetTemp) = 0;
- virtual void binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target) = 0;
+ virtual void copyValue(IR::Expr *source, IR::Expr *target) = 0;
+ virtual void swapValues(IR::Expr *source, IR::Expr *target) = 0;
+ virtual void unop(IR::AluOp oper, IR::Expr *source, IR::Expr *target) = 0;
+ virtual void binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target) = 0;
protected:
- virtual void callBuiltin(IR::Call *c, IR::Temp *result);
+ virtual void callBuiltin(IR::Call *c, IR::Expr *result);
IR::Function *_function; // subclass needs to set
};
diff --git a/src/qml/compiler/qv4isel_util_p.h b/src/qml/compiler/qv4isel_util_p.h
index 09b98a18d1..483e0eb8b4 100644
--- a/src/qml/compiler/qv4isel_util_p.h
+++ b/src/qml/compiler/qv4isel_util_p.h
@@ -153,6 +153,7 @@ protected:
virtual void visitRegExp(IR::RegExp *) {}
virtual void visitName(IR::Name *) {}
virtual void visitTemp(IR::Temp *e) { renumber(e); }
+ virtual void visitArgLocal(IR::ArgLocal *) {}
virtual void visitClosure(IR::Closure *) {}
virtual void visitConvert(IR::Convert *e) { e->expr->accept(this); }
virtual void visitUnop(IR::Unop *e) { e->expr->accept(this); }
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index 501758145a..80528f1007 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -233,6 +233,7 @@ struct RemoveSharedExpressions: IR::StmtVisitor, IR::ExprVisitor
virtual void visitRegExp(RegExp *) {}
virtual void visitName(Name *) {}
virtual void visitTemp(Temp *) {}
+ virtual void visitArgLocal(ArgLocal *) {}
virtual void visitClosure(Closure *) {}
virtual void visitConvert(Convert *e)
@@ -361,9 +362,7 @@ bool operator<(const Temp &t1, const Temp &t2) Q_DECL_NOTHROW
{
if (t1.kind < t2.kind) return true;
if (t1.kind > t2.kind) return false;
- if (t1.index < t2.index) return true;
- if (t1.index > t2.index) return false;
- return t1.scope < t2.scope;
+ return t1.index < t2.index;
}
Function *Module::newFunction(const QString &name, Function *outer)
@@ -510,23 +509,23 @@ Temp *BasicBlock::TEMP(unsigned index)
{
Q_ASSERT(!isRemoved());
Temp *e = function->New<Temp>();
- e->init(Temp::VirtualRegister, index, 0);
+ e->init(Temp::VirtualRegister, index);
return e;
}
-Temp *BasicBlock::ARG(unsigned index, unsigned scope)
+ArgLocal *BasicBlock::ARG(unsigned index, unsigned scope)
{
Q_ASSERT(!isRemoved());
- Temp *e = function->New<Temp>();
- e->init(scope ? Temp::ScopedFormal : Temp::Formal, index, scope);
+ ArgLocal *e = function->New<ArgLocal>();
+ e->init(scope ? ArgLocal::ScopedFormal : ArgLocal::Formal, index, scope);
return e;
}
-Temp *BasicBlock::LOCAL(unsigned index, unsigned scope)
+ArgLocal *BasicBlock::LOCAL(unsigned index, unsigned scope)
{
Q_ASSERT(!isRemoved());
- Temp *e = function->New<Temp>();
- e->init(scope ? Temp::ScopedLocal : Temp::Local, index, scope);
+ ArgLocal *e = function->New<ArgLocal>();
+ e->init(scope ? ArgLocal::ScopedLocal : ArgLocal::Local, index, scope);
return e;
}
@@ -848,6 +847,11 @@ void CloneExpr::visitTemp(Temp *e)
cloned = cloneTemp(e, block->function);
}
+void CloneExpr::visitArgLocal(ArgLocal *e)
+{
+ cloned = cloneArgLocal(e, block->function);
+}
+
void CloneExpr::visitClosure(Closure *e)
{
cloned = block->CLOSURE(e->value);
@@ -1095,12 +1099,6 @@ void IRPrinter::visitTemp(Temp *e)
{
*out << dumpStart(e);
switch (e->kind) {
- case Temp::Formal: *out << '#' << e->index; break;
- case Temp::ScopedFormal: *out << '#' << e->index
- << '@' << e->scope; break;
- case Temp::Local: *out << '$' << e->index; break;
- case Temp::ScopedLocal: *out << '$' << e->index
- << '@' << e->scope; break;
case Temp::VirtualRegister: *out << '%' << e->index; break;
case Temp::PhysicalRegister: *out << (e->type == DoubleType ? "fp" : "r")
<< e->index; break;
@@ -1110,6 +1108,21 @@ void IRPrinter::visitTemp(Temp *e)
*out << dumpEnd(e);
}
+void IRPrinter::visitArgLocal(ArgLocal *e)
+{
+ *out << dumpStart(e);
+ switch (e->kind) {
+ case ArgLocal::Formal: *out << '#' << e->index; break;
+ case ArgLocal::ScopedFormal: *out << '#' << e->index
+ << '@' << e->scope; break;
+ case ArgLocal::Local: *out << '$' << e->index; break;
+ case ArgLocal::ScopedLocal: *out << '$' << e->index
+ << '@' << e->scope; break;
+ default: *out << "INVALID";
+ }
+ *out << dumpEnd(e);
+}
+
void IRPrinter::visitClosure(Closure *e)
{
QString name = e->functionName ? *e->functionName : QString();
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index 2940fd50f4..2551c3d275 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -108,6 +108,7 @@ struct String;
struct RegExp;
struct Name;
struct Temp;
+struct ArgLocal;
struct Closure;
struct Convert;
struct Unop;
@@ -210,6 +211,7 @@ struct ExprVisitor {
virtual void visitRegExp(RegExp *) = 0;
virtual void visitName(Name *) = 0;
virtual void visitTemp(Temp *) = 0;
+ virtual void visitArgLocal(ArgLocal *) = 0;
virtual void visitClosure(Closure *) = 0;
virtual void visitConvert(Convert *) = 0;
virtual void visitUnop(Unop *) = 0;
@@ -260,6 +262,7 @@ struct Q_AUTOTEST_EXPORT Expr {
virtual RegExp *asRegExp() { return 0; }
virtual Name *asName() { return 0; }
virtual Temp *asTemp() { return 0; }
+ virtual ArgLocal *asArgLocal() { return 0; }
virtual Closure *asClosure() { return 0; }
virtual Convert *asConvert() { return 0; }
virtual Unop *asUnop() { return 0; }
@@ -372,33 +375,21 @@ struct Name: Expr {
struct Q_AUTOTEST_EXPORT Temp: Expr {
enum Kind {
- Formal = 0,
- ScopedFormal,
- Local,
- ScopedLocal,
- VirtualRegister,
+ VirtualRegister = 0,
PhysicalRegister,
StackSlot
};
- unsigned index;
- unsigned scope : 27; // how many scopes outside the current one?
- unsigned kind : 3;
- unsigned isArgumentsOrEval : 1;
- unsigned isReadOnly : 1;
+ unsigned index : 28;
+ unsigned kind : 3;
+ unsigned isReadOnly : 1;
// Used when temp is used as base in member expression
MemberExpressionResolver memberResolver;
- void init(unsigned kind, unsigned index, unsigned scope)
+ void init(unsigned kind, unsigned index)
{
- Q_ASSERT((kind == ScopedLocal && scope != 0) ||
- (kind == ScopedFormal && scope != 0) ||
- (scope == 0));
-
this->kind = kind;
this->index = index;
- this->scope = scope;
- this->isArgumentsOrEval = false;
this->isReadOnly = false;
}
@@ -408,16 +399,49 @@ struct Q_AUTOTEST_EXPORT Temp: Expr {
};
inline bool operator==(const Temp &t1, const Temp &t2) Q_DECL_NOTHROW
-{ return t1.index == t2.index && t1.scope == t2.scope && t1.kind == t2.kind && t1.type == t2.type; }
+{ return t1.index == t2.index && t1.kind == t2.kind && t1.type == t2.type; }
inline bool operator!=(const Temp &t1, const Temp &t2) Q_DECL_NOTHROW
{ return !(t1 == t2); }
inline uint qHash(const Temp &t, uint seed = 0) Q_DECL_NOTHROW
-{ return t.index ^ (t.kind | (t.scope << 3)) ^ seed; }
+{ return t.index ^ t.kind ^ seed; }
bool operator<(const Temp &t1, const Temp &t2) Q_DECL_NOTHROW;
+struct Q_AUTOTEST_EXPORT ArgLocal: Expr {
+ enum Kind {
+ Formal = 0,
+ ScopedFormal,
+ Local,
+ ScopedLocal
+ };
+
+ unsigned index;
+ unsigned scope : 29; // how many scopes outside the current one?
+ unsigned kind : 2;
+ unsigned isArgumentsOrEval : 1;
+
+ void init(unsigned kind, unsigned index, unsigned scope)
+ {
+ Q_ASSERT((kind == ScopedLocal && scope != 0) ||
+ (kind == ScopedFormal && scope != 0) ||
+ (scope == 0));
+
+ this->kind = kind;
+ this->index = index;
+ this->scope = scope;
+ this->isArgumentsOrEval = false;
+ }
+
+ virtual void accept(ExprVisitor *v) { v->visitArgLocal(this); }
+ virtual bool isLValue() { return true; }
+ virtual ArgLocal *asArgLocal() { return this; }
+
+ bool operator==(const ArgLocal &other) const
+ { return index == other.index && scope == other.scope && kind == other.kind; }
+};
+
struct Closure: Expr {
int value; // index in _module->functions
const QString *functionName;
@@ -797,8 +821,8 @@ public:
unsigned newTemp();
Temp *TEMP(unsigned kind);
- Temp *ARG(unsigned index, unsigned scope);
- Temp *LOCAL(unsigned index, unsigned scope);
+ ArgLocal *ARG(unsigned index, unsigned scope);
+ ArgLocal *LOCAL(unsigned index, unsigned scope);
Expr *CONST(Type type, double value);
Expr *STRING(const QString *value);
@@ -1040,12 +1064,20 @@ public:
static Temp *cloneTemp(Temp *t, Function *f)
{
Temp *newTemp = f->New<Temp>();
- newTemp->init(t->kind, t->index, t->scope);
+ newTemp->init(t->kind, t->index);
newTemp->type = t->type;
newTemp->memberResolver = t->memberResolver;
return newTemp;
}
+ static ArgLocal *cloneArgLocal(ArgLocal *argLocal, Function *f)
+ {
+ ArgLocal *newArgLocal = f->New<ArgLocal>();
+ newArgLocal->init(argLocal->kind, argLocal->index, argLocal->scope);
+ newArgLocal->type = argLocal->type;
+ return newArgLocal;
+ }
+
protected:
IR::ExprList *clone(IR::ExprList *list);
@@ -1054,6 +1086,7 @@ protected:
virtual void visitRegExp(RegExp *);
virtual void visitName(Name *);
virtual void visitTemp(Temp *);
+ virtual void visitArgLocal(ArgLocal *);
virtual void visitClosure(Closure *);
virtual void visitConvert(Convert *);
virtual void visitUnop(Unop *);
@@ -1093,6 +1126,7 @@ public:
virtual void visitRegExp(RegExp *e);
virtual void visitName(Name *e);
virtual void visitTemp(Temp *e);
+ virtual void visitArgLocal(ArgLocal *e);
virtual void visitClosure(Closure *e);
virtual void visitConvert(Convert *e);
virtual void visitUnop(Unop *e);
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index 842ade4900..4ab2eb397b 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -101,29 +101,6 @@ public:
}
};
-inline bool unescapableTemp(Temp *t, IR::Function *f)
-{
- switch (t->kind) {
- case Temp::Formal:
- case Temp::ScopedFormal:
- case Temp::ScopedLocal:
- return false;
- case Temp::Local:
- return !f->variablesCanEscape();
- default:
- return true;
- }
-}
-
-inline Temp *unescapableTemp(Expr *e, IR::Function *f)
-{
- Temp *t = e->asTemp();
- if (!t)
- return 0;
-
- return unescapableTemp(t, f) ? t : 0;
-}
-
class BasicBlockSet
{
typedef std::vector<int> Numbers;
@@ -625,16 +602,15 @@ class VariableCollector: public StmtVisitor, ExprVisitor {
QSet<Temp> killed;
BasicBlock *currentBB;
- IR::Function *function;
bool isCollectable(Temp *t) const
{
+ Q_UNUSED(t);
Q_ASSERT(t->kind != Temp::PhysicalRegister && t->kind != Temp::StackSlot);
- return unescapableTemp(t, function);
+ return true;
}
public:
VariableCollector(IR::Function *function)
- : function(function)
{
_defsites.reserve(function->tempCount);
A_orig.resize(function->basicBlockCount());
@@ -691,6 +667,7 @@ protected:
virtual void visitString(IR::String *) {}
virtual void visitRegExp(IR::RegExp *) {}
virtual void visitName(Name *) {}
+ virtual void visitArgLocal(ArgLocal *) {}
virtual void visitClosure(Closure *) {}
virtual void visitUnop(Unop *e) { e->expr->accept(this); }
virtual void visitBinop(Binop *e) { e->left->accept(this); e->right->accept(this); }
@@ -760,13 +737,13 @@ void insertPhiNode(const Temp &a, BasicBlock *y, IR::Function *f) {
Phi *phiNode = f->New<Phi>();
phiNode->d = new Stmt::Data;
phiNode->targetTemp = f->New<Temp>();
- phiNode->targetTemp->init(a.kind, a.index, 0);
+ phiNode->targetTemp->init(a.kind, a.index);
y->prependStatement(phiNode);
phiNode->d->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, 0);
+ t->init(a.kind, a.index);
phiNode->d->incoming[i] = t;
}
}
@@ -846,18 +823,18 @@ class VariableRenamer: public StmtVisitor, public ExprVisitor
typedef QHash<unsigned, int> Mapping; // maps from existing/old temp number to the new and unique temp number.
enum { Absent = -1 };
- Mapping localMapping;
Mapping vregMapping;
ProcessedBlocks processed;
bool isRenamable(Temp *t) const
{
+ Q_UNUSED(t);
Q_ASSERT(t->kind != Temp::PhysicalRegister && t->kind != Temp::StackSlot);
- return unescapableTemp(t, function);
+ return true;
}
struct TodoAction {
- enum { RestoreLocal, RestoreVReg, Rename } action;
+ enum { RestoreVReg, Rename } action;
union {
struct {
unsigned temp;
@@ -878,9 +855,9 @@ class VariableRenamer: public StmtVisitor, public ExprVisitor
TodoAction(const Temp &t, int prev)
{
- Q_ASSERT(t.kind == Temp::Local || t.kind == Temp::VirtualRegister);
+ Q_ASSERT(t.kind == Temp::VirtualRegister);
- action = t.kind == Temp::Local ? RestoreLocal : RestoreVReg;
+ action = RestoreVReg;
restoreData.temp = t.index;
restoreData.previous = prev;
}
@@ -902,7 +879,6 @@ public:
, tempCount(0)
, processed(f)
{
- localMapping.reserve(f->tempCount);
vregMapping.reserve(f->tempCount);
todo.reserve(f->basicBlockCount());
}
@@ -919,9 +895,6 @@ public:
case TodoAction::Rename:
rename(todoAction.renameData.basicBlock);
break;
- case TodoAction::RestoreLocal:
- restore(localMapping, todoAction.restoreData.temp, todoAction.restoreData.previous);
- break;
case TodoAction::RestoreVReg:
restore(vregMapping, todoAction.restoreData.temp, todoAction.restoreData.previous);
break;
@@ -987,9 +960,6 @@ private:
{
int nr = Absent;
switch (t.kind) {
- case Temp::Local:
- nr = localMapping.value(t.index, Absent);
- break;
case Temp::VirtualRegister:
nr = vregMapping.value(t.index, Absent);
break;
@@ -1018,10 +988,6 @@ private:
int oldIndex = Absent;
switch (t.kind) {
- case Temp::Local:
- oldIndex = localMapping.value(t.index, Absent);
- localMapping.insert(t.index, newIndex);
- break;
case Temp::VirtualRegister:
oldIndex = vregMapping.value(t.index, Absent);
vregMapping.insert(t.index, newIndex);
@@ -1077,6 +1043,7 @@ protected:
virtual void visitString(IR::String *) {}
virtual void visitRegExp(IR::RegExp *) {}
virtual void visitName(Name *) {}
+ virtual void visitArgLocal(ArgLocal *) {}
virtual void visitClosure(Closure *) {}
virtual void visitUnop(Unop *e) { e->expr->accept(this); }
virtual void visitBinop(Binop *e) { e->left->accept(this); e->right->accept(this); }
@@ -1158,9 +1125,9 @@ struct UntypedTemp {
UntypedTemp(const Temp &t): temp(t) {}
};
inline uint qHash(const UntypedTemp &t, uint seed = 0) Q_DECL_NOTHROW
-{ return t.temp.index ^ (t.temp.kind | (t.temp.scope << 3)) ^ seed; }
+{ return t.temp.index ^ t.temp.kind ^ seed; }
inline bool operator==(const UntypedTemp &t1, const UntypedTemp &t2) Q_DECL_NOTHROW
-{ return t1.temp.index == t2.temp.index && t1.temp.scope == t2.temp.scope && t1.temp.kind == t2.temp.kind; }
+{ return t1.temp.index == t2.temp.index && t1.temp.kind == t2.temp.kind; }
inline bool operator!=(const UntypedTemp &t1, const UntypedTemp &t2) Q_DECL_NOTHROW
{ return !(t1 == t2); }
@@ -1177,7 +1144,6 @@ public:
};
private:
- IR::Function *function;
typedef QHash<UntypedTemp, DefUse> DefUses;
DefUses _defUses;
class Temps: public QVector<Temp> {
@@ -1190,8 +1156,9 @@ private:
Stmt *_stmt;
bool isCollectible(Temp *t) const {
+ Q_UNUSED(t);
Q_ASSERT(t->kind != Temp::PhysicalRegister && t->kind != Temp::StackSlot);
- return unescapableTemp(t, function);
+ return true;
}
void addUse(Temp *t) {
@@ -1216,7 +1183,6 @@ private:
public:
DefUsesCalculator(IR::Function *function)
- : function(function)
{
foreach (BasicBlock *bb, function->basicBlocks()) {
if (bb->isRemoved())
@@ -1369,6 +1335,7 @@ protected:
virtual void visitString(IR::String *) {}
virtual void visitRegExp(IR::RegExp *) {}
virtual void visitName(Name *) {}
+ virtual void visitArgLocal(ArgLocal *) {}
virtual void visitClosure(Closure *) {}
virtual void visitConvert(Convert *e) { e->expr->accept(this); }
virtual void visitUnop(Unop *e) { e->expr->accept(this); }
@@ -1572,15 +1539,13 @@ public:
class EliminateDeadCode: public ExprVisitor {
DefUsesCalculator &_defUses;
StatementWorklist &_worklist;
- IR::Function *function;
bool _sideEffect;
QVector<Temp *> _collectedTemps;
public:
- EliminateDeadCode(DefUsesCalculator &defUses, StatementWorklist &worklist, IR::Function *function)
+ EliminateDeadCode(DefUsesCalculator &defUses, StatementWorklist &worklist)
: _defUses(defUses)
, _worklist(worklist)
- , function(function)
{
_collectedTemps.reserve(8);
}
@@ -1611,11 +1576,6 @@ private:
_collectedTemps.clear();
}
- bool isCollectable(Temp *t) const
- {
- return unescapableTemp(t, function);
- }
-
protected:
virtual void visitConst(Const *) {}
virtual void visitString(IR::String *) {}
@@ -1633,10 +1593,11 @@ protected:
virtual void visitTemp(Temp *e)
{
- if (isCollectable(e))
- _collectedTemps.append(e);
+ _collectedTemps.append(e);
}
+ virtual void visitArgLocal(ArgLocal *) {}
+
virtual void visitClosure(Closure *)
{
markAsSideEffect();
@@ -1764,6 +1725,7 @@ protected:
e->memberResolver = newType.memberResolver;
}
}
+ virtual void visitArgLocal(ArgLocal *) {}
virtual void visitClosure(Closure *) {}
virtual void visitConvert(Convert *e) { e->expr->accept(this); }
virtual void visitUnop(Unop *e) { e->expr->accept(this); }
@@ -1939,20 +1901,11 @@ private:
return ty;
}
- bool isAlwaysVar(Temp *t) {
- if (unescapableTemp(t, function))
- return false;
- t->type = VarType;
- return true;
- }
-
void setType(Expr *e, DiscoveredType ty) {
if (Temp *t = e->asTemp()) {
#if defined(SHOW_SSA)
qout<<"Setting type for "<< (t->scope?"scoped temp ":"temp ") <<t->index<< " to "<<typeName(Type(ty)) << " (" << ty << ")" << endl;
#endif
- if (isAlwaysVar(t))
- ty = DiscoveredType(VarType);
TempTypes::iterator it = _tempTypes.find(*t);
if (it == _tempTypes.end())
it = _tempTypes.insert(*t, DiscoveredType());
@@ -1990,14 +1943,17 @@ protected:
virtual void visitRegExp(IR::RegExp *) { _ty = TypingResult(VarType); }
virtual void visitName(Name *) { _ty = TypingResult(VarType); }
virtual void visitTemp(Temp *e) {
- if (isAlwaysVar(e))
- _ty = TypingResult(VarType);
- else if (e->memberResolver.isValid())
+ if (e->memberResolver.isValid())
_ty = TypingResult(e->memberResolver);
else
_ty = TypingResult(_tempTypes.value(*e));
setType(e, _ty.type);
}
+ virtual void visitArgLocal(ArgLocal *e) {
+ _ty = TypingResult(VarType);
+ setType(e, _ty.type);
+ }
+
virtual void visitClosure(Closure *) { _ty = TypingResult(VarType); }
virtual void visitConvert(Convert *e) {
_ty = TypingResult(e->type);
@@ -2178,6 +2134,8 @@ public:
void run(IR::Function *f)
{
+ Q_UNUSED(f);
+
QVector<UntypedTemp> knownOk;
QList<UntypedTemp> candidates = _defUses.defsUntyped();
while (!candidates.isEmpty()) {
@@ -2220,13 +2178,13 @@ public:
default:
continue;
}
- if (Temp *lt = unescapableTemp(b->left, f))
+ if (Temp *lt = b->left->asTemp())
candidates.append(*lt);
- if (Temp *rt = unescapableTemp(b->right, f))
+ if (Temp *rt = b->right->asTemp())
candidates.append(*rt);
} else if (Unop *u = m->source->asUnop()) {
if (u->op == OpCompl || u->op == OpUPlus) {
- if (Temp *t = unescapableTemp(u->expr, f))
+ if (Temp *t = u->expr->asTemp())
candidates.append(*t);
}
} else {
@@ -2406,6 +2364,26 @@ public:
*conversion.expr = bb->CONVERT(*conversion.expr, conversion.targetType);
} else if (Const *c = (*conversion.expr)->asConst()) {
convertConst(c, conversion.targetType);
+ } else if (ArgLocal *al = (*conversion.expr)->asArgLocal()) {
+ Temp *target = bb->TEMP(bb->newTemp());
+ target->type = conversion.targetType;
+ Expr *convert = bb->CONVERT(al, conversion.targetType);
+ Move *convCall = f->New<Move>();
+ convCall->init(target, convert);
+ _defUses.addTemp(target, convCall, bb);
+
+ Temp *source = bb->TEMP(target->index);
+ source->type = conversion.targetType;
+ _defUses.addUse(*source, conversion.stmt);
+
+ if (conversion.stmt->asPhi()) {
+ // Only temps can be used as arguments to phi nodes, so this is a sanity check...:
+ Q_UNREACHABLE();
+ } else {
+ bb->insertStatementBefore(conversion.stmt, convCall);
+ }
+
+ *conversion.expr = source;
} else if (Temp *t = (*conversion.expr)->asTemp()) {
Temp *target = bb->TEMP(bb->newTemp());
target->type = conversion.targetType;
@@ -2472,6 +2450,7 @@ protected:
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) { run(e->expr, e->type); }
virtual void visitUnop(Unop *e) { run(e->expr, e->type); }
@@ -2945,6 +2924,7 @@ protected:
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); }
@@ -3212,10 +3192,10 @@ void optimizeSSA(IR::Function *function, DefUsesCalculator &defUses, DominatorTr
}
}
- if (Temp *targetTemp = unescapableTemp(m->target, function)) {
+ if (Temp *targetTemp = m->target->asTemp()) {
// dead code elimination:
if (defUses.useCount(*targetTemp) == 0) {
- EliminateDeadCode(defUses, W, function).run(m->source, s);
+ EliminateDeadCode(defUses, W).run(m->source, s);
if (!m->source)
W.clear(s);
continue;
@@ -3250,7 +3230,7 @@ void optimizeSSA(IR::Function *function, DefUsesCalculator &defUses, DominatorTr
}
// copy propagation:
- if (Temp *sourceTemp = unescapableTemp(m->source, function)) {
+ if (Temp *sourceTemp = m->source->asTemp()) {
QVector<Stmt *> newT2Uses;
replaceUses(targetTemp, sourceTemp, W, &newT2Uses);
defUses.removeUse(s, *sourceTemp);
@@ -3445,14 +3425,10 @@ void optimizeSSA(IR::Function *function, DefUsesCalculator &defUses, DominatorTr
}
class InputOutputCollector: protected StmtVisitor, protected ExprVisitor {
- IR::Function *function;
-
public:
QList<Temp> inputs;
QList<Temp> outputs;
- InputOutputCollector(IR::Function *f): function(f) {}
-
void collect(Stmt *s) {
inputs.clear();
outputs.clear();
@@ -3465,9 +3441,9 @@ protected:
virtual void visitRegExp(IR::RegExp *) {}
virtual void visitName(Name *) {}
virtual void visitTemp(Temp *e) {
- if (unescapableTemp(e, function))
- inputs.append(*e);
+ inputs.append(*e);
}
+ virtual void visitArgLocal(ArgLocal *) {}
virtual void visitClosure(Closure *) {}
virtual void visitConvert(Convert *e) { e->expr->accept(this); }
virtual void visitUnop(Unop *e) { e->expr->accept(this); }
@@ -3488,10 +3464,7 @@ protected:
virtual void visitMove(Move *s) {
s->source->accept(this);
if (Temp *t = s->target->asTemp()) {
- if (unescapableTemp(t, function))
- outputs.append(*t);
- else
- s->target->accept(this);
+ outputs.append(*t);
} else {
s->target->accept(this);
}
@@ -3541,7 +3514,7 @@ public:
for (int i = function->basicBlockCount() - 1; i >= 0; --i) {
BasicBlock *bb = function->basicBlock(i);
- buildIntervals(bb, startEndLoops.value(bb, 0), function);
+ buildIntervals(bb, startEndLoops.value(bb, 0));
}
_sortedIntervals.reserve(_intervals.size());
@@ -3578,7 +3551,7 @@ public:
}
private:
- void buildIntervals(BasicBlock *bb, BasicBlock *loopEnd, IR::Function *function)
+ void buildIntervals(BasicBlock *bb, BasicBlock *loopEnd)
{
LiveRegs live;
foreach (BasicBlock *successor, bb->out) {
@@ -3601,7 +3574,7 @@ private:
foreach (const Temp &opd, live)
_intervals[opd].addRange(statements.first()->id, statements.last()->id);
- InputOutputCollector collector(function);
+ InputOutputCollector collector;
for (int i = statements.size() - 1; i >= 0; --i) {
Stmt *s = statements[i];
if (Phi *phi = s->asPhi()) {
@@ -3990,8 +3963,6 @@ static inline bool overlappingStorage(const Temp &t1, const Temp &t2)
// This is the same as the operator==, but for one detail: memory locations are not sensitive
// to types, and neither are general-purpose registers.
- if (t1.scope != t2.scope)
- return false;
if (t1.index != t2.index)
return false; // different position, where-ever that may (physically) be.
if (t1.kind != t2.kind)
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp
index cd44b537df..f090e7d506 100644
--- a/src/qml/jit/qv4assembler.cpp
+++ b/src/qml/jit/qv4assembler.cpp
@@ -223,10 +223,27 @@ void Assembler::generateCJumpOnCompare(RelationalCondition cond, RegisterID left
}
}
-Assembler::Pointer Assembler::loadTempAddress(RegisterID baseReg, IR::Temp *t)
+Assembler::Pointer Assembler::loadAddress(RegisterID tmp, IR::Expr *e)
+{
+ IR::Temp *t = e->asTemp();
+ if (t)
+ return loadTempAddress(t);
+ else
+ return loadArgLocalAddress(tmp, e->asArgLocal());
+}
+
+Assembler::Pointer Assembler::loadTempAddress(IR::Temp *t)
+{
+ if (t->kind == IR::Temp::StackSlot)
+ return stackSlotPointer(t);
+ else
+ Q_UNREACHABLE();
+}
+
+Assembler::Pointer Assembler::loadArgLocalAddress(RegisterID baseReg, IR::ArgLocal *al)
{
int32_t offset = 0;
- int scope = t->scope;
+ int scope = al->scope;
RegisterID context = ContextRegister;
if (scope) {
loadPtr(Address(ContextRegister, qOffsetOf(ExecutionContext, outer)), baseReg);
@@ -237,19 +254,16 @@ Assembler::Pointer Assembler::loadTempAddress(RegisterID baseReg, IR::Temp *t)
--scope;
}
}
- switch (t->kind) {
- case IR::Temp::Formal:
- case IR::Temp::ScopedFormal: {
+ switch (al->kind) {
+ case IR::ArgLocal::Formal:
+ case IR::ArgLocal::ScopedFormal: {
loadPtr(Address(context, qOffsetOf(ExecutionContext, callData)), baseReg);
- offset = sizeof(CallData) + (t->index - 1) * sizeof(Value);
+ offset = sizeof(CallData) + (al->index - 1) * sizeof(Value);
} break;
- case IR::Temp::Local:
- case IR::Temp::ScopedLocal: {
+ case IR::ArgLocal::Local:
+ case IR::ArgLocal::ScopedLocal: {
loadPtr(Address(context, qOffsetOf(CallContext, locals)), baseReg);
- offset = t->index * sizeof(Value);
- } break;
- case IR::Temp::StackSlot: {
- return stackSlotPointer(t);
+ offset = al->index * sizeof(Value);
} break;
default:
Q_UNREACHABLE();
@@ -273,9 +287,9 @@ void Assembler::loadStringRef(RegisterID reg, const QString &string)
addPtr(TrustedImmPtr(id * sizeof(QV4::StringValue)), reg);
}
-void Assembler::storeValue(QV4::Primitive value, IR::Temp* destination)
+void Assembler::storeValue(QV4::Primitive value, IR::Expr *destination)
{
- Address addr = loadTempAddress(ScratchRegister, destination);
+ Address addr = loadAddress(ScratchRegister, destination);
storeValue(value, addr);
}
@@ -347,13 +361,12 @@ Assembler::Jump Assembler::genTryDoubleConversion(IR::Expr *src, Assembler::FPRe
break;
}
- IR::Temp *sourceTemp = src->asTemp();
- Q_ASSERT(sourceTemp);
+ Q_ASSERT(src->asTemp() || src->asArgLocal());
// It's not a number type, so it cannot be in a register.
- Q_ASSERT(sourceTemp->kind != IR::Temp::PhysicalRegister || sourceTemp->type == IR::BoolType);
+ Q_ASSERT(src->asArgLocal() || src->asTemp()->kind != IR::Temp::PhysicalRegister || src->type == IR::BoolType);
- Assembler::Pointer tagAddr = loadTempAddress(Assembler::ScratchRegister, sourceTemp);
+ Assembler::Pointer tagAddr = loadAddress(Assembler::ScratchRegister, src);
tagAddr.offset += 4;
load32(tagAddr, Assembler::ScratchRegister);
diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h
index 6fde517e1f..90387dcf79 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -460,8 +460,10 @@ public:
QString string;
};
struct Reference {
- Reference(IR::Temp *value) : value(value) {}
- IR::Temp *value;
+ Reference(IR::Expr *value) : value(value) {
+ Q_ASSERT(value->asTemp() || value->asArgLocal());
+ }
+ IR::Expr *value;
};
struct ReentryBlock {
@@ -504,13 +506,14 @@ public:
Jump genTryDoubleConversion(IR::Expr *src, Assembler::FPRegisterID dest);
Assembler::Jump branchDouble(bool invertCondition, IR::AluOp op, IR::Expr *left, IR::Expr *right);
- Pointer loadTempAddress(RegisterID baseReg, IR::Temp *t);
+ Pointer loadAddress(RegisterID tmp, IR::Expr *t);
+ Pointer loadTempAddress(IR::Temp *t);
+ Pointer loadArgLocalAddress(RegisterID baseReg, IR::ArgLocal *al);
Pointer loadStringAddress(RegisterID reg, const QString &string);
void loadStringRef(RegisterID reg, const QString &string);
Pointer stackSlotPointer(IR::Temp *t) const
{
Q_ASSERT(t->kind == IR::Temp::StackSlot);
- Q_ASSERT(t->scope == 0);
return Pointer(_stackLayout.stackSlotPointer(t->index));
}
@@ -585,7 +588,7 @@ public:
void loadArgumentInRegister(Reference temp, RegisterID dest, int argumentNumber)
{
Q_ASSERT(temp.value);
- Pointer addr = loadTempAddress(dest, temp.value);
+ Pointer addr = loadAddress(dest, temp.value);
loadArgumentInRegister(addr, dest, argumentNumber);
}
@@ -603,12 +606,25 @@ public:
{
Q_UNUSED(argumentNumber);
- if (!temp) {
+ if (temp) {
+ Pointer addr = loadTempAddress(temp);
+ load64(addr, dest);
+ } else {
QV4::Value undefined = QV4::Primitive::undefinedValue();
move(TrustedImm64(undefined.val), dest);
- } else {
- Pointer addr = loadTempAddress(dest, temp);
+ }
+ }
+
+ void loadArgumentInRegister(IR::ArgLocal* al, RegisterID dest, int argumentNumber)
+ {
+ Q_UNUSED(argumentNumber);
+
+ if (al) {
+ Pointer addr = loadArgLocalAddress(dest, al);
load64(addr, dest);
+ } else {
+ QV4::Value undefined = QV4::Primitive::undefinedValue();
+ move(TrustedImm64(undefined.val), dest);
}
}
@@ -627,10 +643,12 @@ public:
if (!expr) {
QV4::Value undefined = QV4::Primitive::undefinedValue();
move(TrustedImm64(undefined.val), dest);
- } else if (expr->asTemp()){
- loadArgumentInRegister(expr->asTemp(), dest, argumentNumber);
- } else if (expr->asConst()) {
- loadArgumentInRegister(expr->asConst(), dest, argumentNumber);
+ } else if (IR::Temp *t = expr->asTemp()){
+ loadArgumentInRegister(t, dest, argumentNumber);
+ } else if (IR::ArgLocal *al = expr->asArgLocal()) {
+ loadArgumentInRegister(al, dest, argumentNumber);
+ } else if (IR::Const *c = expr->asConst()) {
+ loadArgumentInRegister(c, dest, argumentNumber);
} else {
Q_ASSERT(!"unimplemented expression type in loadArgument");
}
@@ -704,20 +722,26 @@ public:
}
#endif
- void storeReturnValue(IR::Temp *temp)
+ void storeReturnValue(IR::Expr *target)
{
- if (!temp)
+ if (!target)
return;
- if (temp->kind == IR::Temp::PhysicalRegister) {
- if (temp->type == IR::DoubleType)
- storeReturnValue((FPRegisterID) temp->index);
- else if (temp->type == IR::UInt32Type)
- storeUInt32ReturnValue((RegisterID) temp->index);
- else
- storeReturnValue((RegisterID) temp->index);
- } else {
- Pointer addr = loadTempAddress(ScratchRegister, temp);
+ if (IR::Temp *temp = target->asTemp()) {
+ if (temp->kind == IR::Temp::PhysicalRegister) {
+ if (temp->type == IR::DoubleType)
+ storeReturnValue((FPRegisterID) temp->index);
+ else if (temp->type == IR::UInt32Type)
+ storeUInt32ReturnValue((RegisterID) temp->index);
+ else
+ storeReturnValue((RegisterID) temp->index);
+ return;
+ } else {
+ Pointer addr = loadTempAddress(temp);
+ storeReturnValue(addr);
+ }
+ } else if (IR::ArgLocal *al = target->asArgLocal()) {
+ Pointer addr = loadArgLocalAddress(ScratchRegister, al);
storeReturnValue(addr);
}
}
@@ -775,7 +799,7 @@ public:
{
Q_ASSERT (temp.value);
- Pointer ptr = loadTempAddress(ScratchRegister, temp.value);
+ Pointer ptr = loadAddress(ScratchRegister, temp.value);
loadArgumentOnStack<StackSlot>(ptr, argumentNumber);
}
@@ -807,30 +831,32 @@ public:
poke(TrustedImmPtr(name), StackSlot);
}
- void loadDouble(IR::Temp* temp, FPRegisterID dest)
+ void loadDouble(IR::Expr *source, FPRegisterID dest)
{
- if (temp->kind == IR::Temp::PhysicalRegister) {
- moveDouble((FPRegisterID) temp->index, dest);
+ IR::Temp *sourceTemp = source->asTemp();
+ if (sourceTemp && sourceTemp->kind == IR::Temp::PhysicalRegister) {
+ moveDouble((FPRegisterID) sourceTemp->index, dest);
return;
}
- Pointer ptr = loadTempAddress(ScratchRegister, temp);
+ Pointer ptr = loadAddress(ScratchRegister, source);
loadDouble(ptr, dest);
}
- void storeDouble(FPRegisterID source, IR::Temp* temp)
+ void storeDouble(FPRegisterID source, IR::Expr* target)
{
- if (temp->kind == IR::Temp::PhysicalRegister) {
- moveDouble(source, (FPRegisterID) temp->index);
+ IR::Temp *targetTemp = target->asTemp();
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) {
+ moveDouble(source, (FPRegisterID) targetTemp->index);
return;
}
#if QT_POINTER_SIZE == 8
moveDoubleTo64(source, ReturnValueRegister);
move(TrustedImm64(QV4::Value::NaNEncodeMask), ScratchRegister);
xor64(ScratchRegister, ReturnValueRegister);
- Pointer ptr = loadTempAddress(ScratchRegister, temp);
+ Pointer ptr = loadAddress(ScratchRegister, target);
store64(ReturnValueRegister, ptr);
#else
- Pointer ptr = loadTempAddress(ScratchRegister, temp);
+ Pointer ptr = loadAddress(ScratchRegister, target);
storeDouble(source, ptr);
#endif
}
@@ -862,11 +888,11 @@ public:
void copyValue(Result result, IR::Expr* source);
// The scratch register is used to calculate the temp address for the source.
- void memcopyValue(Pointer target, IR::Temp *sourceTemp, RegisterID scratchRegister)
+ void memcopyValue(Pointer target, IR::Expr *source, RegisterID scratchRegister)
{
- Q_ASSERT(sourceTemp->kind != IR::Temp::PhysicalRegister);
+ Q_ASSERT(!source->asTemp() || source->asTemp()->kind != IR::Temp::PhysicalRegister);
Q_ASSERT(target.base != scratchRegister);
- JSC::MacroAssembler::loadDouble(loadTempAddress(scratchRegister, sourceTemp), FPGpr0);
+ JSC::MacroAssembler::loadDouble(loadAddress(scratchRegister, source), FPGpr0);
JSC::MacroAssembler::storeDouble(FPGpr0, target);
}
@@ -888,7 +914,7 @@ public:
#endif
}
- void storeValue(QV4::Primitive value, IR::Temp* temp);
+ void storeValue(QV4::Primitive value, IR::Expr* temp);
void enterStandardStackFrame();
void leaveStandardStackFrame();
@@ -1050,13 +1076,11 @@ public:
return Pointer(addr);
}
- IR::Temp *t = e->asTemp();
- Q_ASSERT(t);
- if (t->kind != IR::Temp::PhysicalRegister)
- return loadTempAddress(tmpReg, t);
+ if (IR::Temp *t = e->asTemp())
+ if (t->kind == IR::Temp::PhysicalRegister)
+ return Pointer(_stackLayout.savedRegPointer(offset));
-
- return Pointer(_stackLayout.savedRegPointer(offset));
+ return loadAddress(tmpReg, e);
}
void storeBool(RegisterID reg, Pointer addr)
@@ -1071,24 +1095,31 @@ public:
move(src, dest);
}
- void storeBool(RegisterID reg, IR::Temp *target)
+ void storeBool(RegisterID reg, IR::Expr *target)
{
- if (target->kind == IR::Temp::PhysicalRegister) {
- move(reg, (RegisterID) target->index);
- } else {
- Pointer addr = loadTempAddress(ScratchRegister, target);
- storeBool(reg, addr);
+ if (IR::Temp *targetTemp = target->asTemp()) {
+ if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ move(reg, (RegisterID) targetTemp->index);
+ return;
+ }
}
+
+ Pointer addr = loadAddress(ScratchRegister, target);
+ storeBool(reg, addr);
}
- void storeBool(bool value, IR::Temp *target) {
+ void storeBool(bool value, IR::Expr *target) {
TrustedImm32 trustedValue(value ? 1 : 0);
- if (target->kind == IR::Temp::PhysicalRegister) {
- move(trustedValue, (RegisterID) target->index);
- } else {
- move(trustedValue, ScratchRegister);
- storeBool(ScratchRegister, target);
+
+ if (IR::Temp *targetTemp = target->asTemp()) {
+ if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ move(trustedValue, (RegisterID) targetTemp->index);
+ return;
+ }
}
+
+ move(trustedValue, ScratchRegister);
+ storeBool(ScratchRegister, target);
}
void storeInt32(RegisterID src, RegisterID dest)
@@ -1103,12 +1134,17 @@ public:
store32(TrustedImm32(QV4::Primitive::fromInt32(0).tag), addr);
}
- void storeInt32(RegisterID reg, IR::Temp *target)
+ void storeInt32(RegisterID reg, IR::Expr *target)
{
- if (target->kind == IR::Temp::PhysicalRegister) {
- move(reg, (RegisterID) target->index);
- } else {
- Pointer addr = loadTempAddress(ScratchRegister, target);
+ if (IR::Temp *targetTemp = target->asTemp()) {
+ if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ move(reg, (RegisterID) targetTemp->index);
+ } else {
+ Pointer addr = loadTempAddress(targetTemp);
+ storeInt32(reg, addr);
+ }
+ } else if (IR::ArgLocal *al = target->asArgLocal()) {
+ Pointer addr = loadArgLocalAddress(ScratchRegister, al);
storeInt32(reg, addr);
}
}
@@ -1130,12 +1166,13 @@ public:
done.link(this);
}
- void storeUInt32(RegisterID reg, IR::Temp *target)
+ void storeUInt32(RegisterID reg, IR::Expr *target)
{
- if (target->kind == IR::Temp::PhysicalRegister) {
- move(reg, (RegisterID) target->index);
+ IR::Temp *targetTemp = target->asTemp();
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) {
+ move(reg, (RegisterID) targetTemp->index);
} else {
- Pointer addr = loadTempAddress(ScratchRegister, target);
+ Pointer addr = loadAddress(ScratchRegister, target);
storeUInt32(reg, addr);
}
}
@@ -1157,12 +1194,11 @@ public:
return target;
}
- IR::Temp *t = e->asTemp();
- Q_ASSERT(t);
- if (t->kind == IR::Temp::PhysicalRegister)
- return (FPRegisterID) t->index;
+ if (IR::Temp *t = e->asTemp())
+ if (t->kind == IR::Temp::PhysicalRegister)
+ return (FPRegisterID) t->index;
- loadDouble(t, target);
+ loadDouble(e, target);
return target;
}
@@ -1178,12 +1214,11 @@ public:
return scratchReg;
}
- IR::Temp *t = e->asTemp();
- Q_ASSERT(t);
- if (t->kind == IR::Temp::PhysicalRegister)
- return (RegisterID) t->index;
+ if (IR::Temp *t = e->asTemp())
+ if (t->kind == IR::Temp::PhysicalRegister)
+ return (RegisterID) t->index;
- return toInt32Register(loadTempAddress(scratchReg, t), scratchReg);
+ return toInt32Register(loadAddress(scratchReg, e), scratchReg);
}
RegisterID toInt32Register(Pointer addr, RegisterID scratchReg)
@@ -1199,12 +1234,11 @@ public:
return scratchReg;
}
- IR::Temp *t = e->asTemp();
- Q_ASSERT(t);
- if (t->kind == IR::Temp::PhysicalRegister)
- return (RegisterID) t->index;
+ if (IR::Temp *t = e->asTemp())
+ if (t->kind == IR::Temp::PhysicalRegister)
+ return (RegisterID) t->index;
- return toUInt32Register(loadTempAddress(scratchReg, t), scratchReg);
+ return toUInt32Register(loadAddress(scratchReg, e), scratchReg);
}
RegisterID toUInt32Register(Pointer addr, RegisterID scratchReg)
@@ -1291,17 +1325,15 @@ void Assembler::copyValue(Result result, IR::Expr* source)
storeUInt32(reg, result);
} else if (source->type == IR::DoubleType) {
storeDouble(toDoubleRegister(source), result);
- } else if (IR::Temp *temp = source->asTemp()) {
+ } else if (source->asTemp() || source->asArgLocal()) {
#ifdef VALUE_FITS_IN_REGISTER
- Q_UNUSED(temp);
-
- // Use ReturnValueRegister as "scratch" register because loadArgument
- // and storeArgument are functions that may need a scratch register themselves.
- loadArgumentInRegister(source, ReturnValueRegister, 0);
- storeReturnValue(result);
+ // Use ReturnValueRegister as "scratch" register because loadArgument
+ // and storeArgument are functions that may need a scratch register themselves.
+ loadArgumentInRegister(source, ReturnValueRegister, 0);
+ storeReturnValue(result);
#else
- loadDouble(temp, FPGpr0);
- storeDouble(FPGpr0, result);
+ loadDouble(source, FPGpr0);
+ storeDouble(FPGpr0, result);
#endif
} else if (IR::Const *c = source->asConst()) {
QV4::Primitive v = convertToValue(c);
diff --git a/src/qml/jit/qv4binop.cpp b/src/qml/jit/qv4binop.cpp
index 344bbf56e0..a19072f52e 100644
--- a/src/qml/jit/qv4binop.cpp
+++ b/src/qml/jit/qv4binop.cpp
@@ -112,7 +112,7 @@ const Binop::OpInfo Binop::operations[IR::LastAluOp + 1] = {
-void Binop::generate(IR::Expr *lhs, IR::Expr *rhs, IR::Temp *target)
+void Binop::generate(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
{
if (op != IR::OpMod
&& lhs->type == IR::DoubleType && rhs->type == IR::DoubleType
@@ -156,14 +156,15 @@ void Binop::generate(IR::Expr *lhs, IR::Expr *rhs, IR::Temp *target)
}
-void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Temp *target)
+void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
{
Q_ASSERT(lhs->asConst() == 0 || rhs->asConst() == 0);
Q_ASSERT(isPregOrConst(lhs));
Q_ASSERT(isPregOrConst(rhs));
+ IR::Temp *targetTemp = target->asTemp();
Assembler::FPRegisterID targetReg;
- if (target->kind == IR::Temp::PhysicalRegister)
- targetReg = (Assembler::FPRegisterID) target->index;
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister)
+ targetReg = (Assembler::FPRegisterID) targetTemp->index;
else
targetReg = Assembler::FPGpr0;
@@ -232,31 +233,33 @@ void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Temp *target)
} return;
}
- if (target->kind != IR::Temp::PhysicalRegister)
+ if (!targetTemp || targetTemp->kind != IR::Temp::PhysicalRegister)
as->storeDouble(Assembler::FPGpr0, target);
}
-bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target)
+bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target)
{
Q_ASSERT(leftSource->type == IR::SInt32Type);
+ IR::Temp *targetTemp = target->asTemp();
Assembler::RegisterID targetReg = Assembler::ReturnValueRegister;
- if (target->kind == IR::Temp::PhysicalRegister) {
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) {
// We try to load leftSource into the target's register, but we can't do that if
// the target register is the same as rightSource.
IR::Temp *rhs = rightSource->asTemp();
- if (!rhs || rhs->kind != IR::Temp::PhysicalRegister || rhs->index != target->index)
- targetReg = (Assembler::RegisterID) target->index;
+ if (!rhs || rhs->kind != IR::Temp::PhysicalRegister || rhs->index != targetTemp->index)
+ targetReg = (Assembler::RegisterID) targetTemp->index;
}
switch (op) {
case IR::OpBitAnd: {
Q_ASSERT(rightSource->type == IR::SInt32Type);
if (rightSource->asTemp() && rightSource->asTemp()->kind == IR::Temp::PhysicalRegister
- && target->kind == IR::Temp::PhysicalRegister
- && target->index == rightSource->asTemp()->index) {
+ && targetTemp
+ && targetTemp->kind == IR::Temp::PhysicalRegister
+ && targetTemp->index == rightSource->asTemp()->index) {
as->and32(as->toInt32Register(leftSource, Assembler::ScratchRegister),
- (Assembler::RegisterID) target->index);
+ (Assembler::RegisterID) targetTemp->index);
return true;
}
@@ -268,10 +271,11 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *ta
case IR::OpBitOr: {
Q_ASSERT(rightSource->type == IR::SInt32Type);
if (rightSource->asTemp() && rightSource->asTemp()->kind == IR::Temp::PhysicalRegister
- && target->kind == IR::Temp::PhysicalRegister
- && target->index == rightSource->asTemp()->index) {
+ && targetTemp
+ && targetTemp->kind == IR::Temp::PhysicalRegister
+ && targetTemp->index == rightSource->asTemp()->index) {
as->or32(as->toInt32Register(leftSource, Assembler::ScratchRegister),
- (Assembler::RegisterID) target->index);
+ (Assembler::RegisterID) targetTemp->index);
return true;
}
@@ -283,10 +287,11 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *ta
case IR::OpBitXor: {
Q_ASSERT(rightSource->type == IR::SInt32Type);
if (rightSource->asTemp() && rightSource->asTemp()->kind == IR::Temp::PhysicalRegister
- && target->kind == IR::Temp::PhysicalRegister
- && target->index == rightSource->asTemp()->index) {
+ && targetTemp
+ && targetTemp->kind == IR::Temp::PhysicalRegister
+ && targetTemp->index == rightSource->asTemp()->index) {
as->xor32(as->toInt32Register(leftSource, Assembler::ScratchRegister),
- (Assembler::RegisterID) target->index);
+ (Assembler::RegisterID) targetTemp->index);
return true;
}
@@ -370,9 +375,10 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *ta
Q_ASSERT(rightSource->type == IR::SInt32Type);
if (rightSource->asTemp() && rightSource->asTemp()->kind == IR::Temp::PhysicalRegister
- && target->kind == IR::Temp::PhysicalRegister
- && target->index == rightSource->asTemp()->index) {
- Assembler::RegisterID targetReg = (Assembler::RegisterID) target->index;
+ && targetTemp
+ && targetTemp->kind == IR::Temp::PhysicalRegister
+ && targetTemp->index == rightSource->asTemp()->index) {
+ Assembler::RegisterID targetReg = (Assembler::RegisterID) targetTemp->index;
as->move(targetReg, Assembler::ScratchRegister);
as->move(as->toInt32Register(leftSource, targetReg), targetReg);
as->sub32(Assembler::ScratchRegister, targetReg);
@@ -407,7 +413,7 @@ static inline Assembler::FPRegisterID getFreeFPReg(IR::Expr *shouldNotOverlap, u
return Assembler::FPRegisterID(hint);
}
-Assembler::Jump Binop::genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target)
+Assembler::Jump Binop::genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target)
{
Assembler::Jump done;
diff --git a/src/qml/jit/qv4binop_p.h b/src/qml/jit/qv4binop_p.h
index a6292e6fb5..8c7fa4337a 100644
--- a/src/qml/jit/qv4binop_p.h
+++ b/src/qml/jit/qv4binop_p.h
@@ -58,10 +58,10 @@ struct Binop {
, op(operation)
{}
- void generate(IR::Expr *lhs, IR::Expr *rhs, IR::Temp *target);
- void doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Temp *target);
- bool int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target);
- Assembler::Jump genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target);
+ void generate(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target);
+ void doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target);
+ bool int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target);
+ Assembler::Jump genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target);
typedef Assembler::Jump (Binop::*MemRegOp)(Assembler::Address, Assembler::RegisterID);
typedef Assembler::Jump (Binop::*ImmRegOp)(Assembler::TrustedImm32, Assembler::RegisterID);
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index 3307fcc0d1..d82fa990f4 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -389,7 +389,7 @@ QV4::CompiledData::CompilationUnit *InstructionSelection::backendCompileStep()
return compilationUnit;
}
-void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Temp *result)
+void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result)
{
prepareCallData(args, 0);
@@ -408,52 +408,52 @@ void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args
}
void InstructionSelection::callBuiltinTypeofMember(IR::Expr *base, const QString &name,
- IR::Temp *result)
+ IR::Expr *result)
{
generateFunctionCall(result, Runtime::typeofMember, Assembler::ContextRegister,
Assembler::PointerToValue(base), Assembler::PointerToString(name));
}
void InstructionSelection::callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index,
- IR::Temp *result)
+ IR::Expr *result)
{
generateFunctionCall(result, Runtime::typeofElement,
Assembler::ContextRegister,
Assembler::PointerToValue(base), Assembler::PointerToValue(index));
}
-void InstructionSelection::callBuiltinTypeofName(const QString &name, IR::Temp *result)
+void InstructionSelection::callBuiltinTypeofName(const QString &name, IR::Expr *result)
{
generateFunctionCall(result, Runtime::typeofName, Assembler::ContextRegister,
Assembler::PointerToString(name));
}
-void InstructionSelection::callBuiltinTypeofValue(IR::Expr *value, IR::Temp *result)
+void InstructionSelection::callBuiltinTypeofValue(IR::Expr *value, IR::Expr *result)
{
generateFunctionCall(result, Runtime::typeofValue, Assembler::ContextRegister,
Assembler::PointerToValue(value));
}
-void InstructionSelection::callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result)
+void InstructionSelection::callBuiltinDeleteMember(IR::Expr *base, const QString &name, IR::Expr *result)
{
generateFunctionCall(result, Runtime::deleteMember, Assembler::ContextRegister,
Assembler::Reference(base), Assembler::PointerToString(name));
}
-void InstructionSelection::callBuiltinDeleteSubscript(IR::Temp *base, IR::Expr *index,
- IR::Temp *result)
+void InstructionSelection::callBuiltinDeleteSubscript(IR::Expr *base, IR::Expr *index,
+ IR::Expr *result)
{
generateFunctionCall(result, Runtime::deleteElement, Assembler::ContextRegister,
Assembler::Reference(base), Assembler::PointerToValue(index));
}
-void InstructionSelection::callBuiltinDeleteName(const QString &name, IR::Temp *result)
+void InstructionSelection::callBuiltinDeleteName(const QString &name, IR::Expr *result)
{
generateFunctionCall(result, Runtime::deleteName, Assembler::ContextRegister,
Assembler::PointerToString(name));
}
-void InstructionSelection::callBuiltinDeleteValue(IR::Temp *result)
+void InstructionSelection::callBuiltinDeleteValue(IR::Expr *result)
{
_as->storeValue(Primitive::fromBoolean(false), result);
}
@@ -469,7 +469,7 @@ void InstructionSelection::callBuiltinReThrow()
_as->jumpToExceptionHandler();
}
-void InstructionSelection::callBuiltinUnwindException(IR::Temp *result)
+void InstructionSelection::callBuiltinUnwindException(IR::Expr *result)
{
generateFunctionCall(result, Runtime::unwindException, Assembler::ContextRegister);
@@ -481,7 +481,7 @@ void InstructionSelection::callBuiltinPushCatchScope(const QString &exceptionNam
generateFunctionCall(Assembler::ContextRegister, Runtime::pushCatchScope, Assembler::ContextRegister, s);
}
-void InstructionSelection::callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Temp *result)
+void InstructionSelection::callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Expr *result)
{
Q_ASSERT(arg);
Q_ASSERT(result);
@@ -489,7 +489,7 @@ void InstructionSelection::callBuiltinForeachIteratorObject(IR::Expr *arg, IR::T
generateFunctionCall(result, Runtime::foreachIterator, Assembler::ContextRegister, Assembler::PointerToValue(arg));
}
-void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result)
+void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Expr *arg, IR::Expr *result)
{
Q_ASSERT(arg);
Q_ASSERT(result);
@@ -497,7 +497,7 @@ void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Temp *arg, IR:
generateFunctionCall(result, Runtime::foreachNextPropertyName, Assembler::Reference(arg));
}
-void InstructionSelection::callBuiltinPushWithScope(IR::Temp *arg)
+void InstructionSelection::callBuiltinPushWithScope(IR::Expr *arg)
{
Q_ASSERT(arg);
@@ -515,7 +515,7 @@ void InstructionSelection::callBuiltinDeclareVar(bool deletable, const QString &
Assembler::TrustedImm32(deletable), Assembler::PointerToString(name));
}
-void InstructionSelection::callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args)
+void InstructionSelection::callBuiltinDefineArray(IR::Expr *result, IR::ExprList *args)
{
Q_ASSERT(result);
@@ -524,7 +524,7 @@ void InstructionSelection::callBuiltinDefineArray(IR::Temp *result, IR::ExprList
baseAddressForCallArguments(), Assembler::TrustedImm32(length));
}
-void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray)
+void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Expr *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray)
{
Q_ASSERT(result);
@@ -605,7 +605,7 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, int
Assembler::TrustedImm32(arrayValueCount), Assembler::TrustedImm32(arrayGetterSetterCount | (needSparseArray << 30)));
}
-void InstructionSelection::callBuiltinSetupArgumentObject(IR::Temp *result)
+void InstructionSelection::callBuiltinSetupArgumentObject(IR::Expr *result)
{
generateFunctionCall(result, Runtime::setupArgumentsObject, Assembler::ContextRegister);
}
@@ -615,7 +615,7 @@ void InstructionSelection::callBuiltinConvertThisToObject()
generateFunctionCall(Assembler::Void, Runtime::convertThisToObject, Assembler::ContextRegister);
}
-void InstructionSelection::callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result)
+void InstructionSelection::callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result)
{
Q_ASSERT(value);
@@ -625,7 +625,7 @@ void InstructionSelection::callValue(IR::Temp *value, IR::ExprList *args, IR::Te
baseAddressForCallData());
}
-void InstructionSelection::loadThisObject(IR::Temp *temp)
+void InstructionSelection::loadThisObject(IR::Expr *temp)
{
_as->loadPtr(Address(Assembler::ContextRegister, qOffsetOf(ExecutionContext, callData)), Assembler::ScratchRegister);
#if defined(VALUE_FITS_IN_REGISTER)
@@ -637,60 +637,63 @@ void InstructionSelection::loadThisObject(IR::Temp *temp)
#endif
}
-void InstructionSelection::loadQmlIdArray(IR::Temp *temp)
+void InstructionSelection::loadQmlIdArray(IR::Expr *temp)
{
generateFunctionCall(temp, Runtime::getQmlIdArray, Assembler::ContextRegister);
}
-void InstructionSelection::loadQmlImportedScripts(IR::Temp *temp)
+void InstructionSelection::loadQmlImportedScripts(IR::Expr *temp)
{
generateFunctionCall(temp, Runtime::getQmlImportedScripts, Assembler::ContextRegister);
}
-void InstructionSelection::loadQmlContextObject(IR::Temp *temp)
+void InstructionSelection::loadQmlContextObject(IR::Expr *temp)
{
generateFunctionCall(temp, Runtime::getQmlContextObject, Assembler::ContextRegister);
}
-void InstructionSelection::loadQmlScopeObject(IR::Temp *temp)
+void InstructionSelection::loadQmlScopeObject(IR::Expr *temp)
{
generateFunctionCall(temp, Runtime::getQmlScopeObject, Assembler::ContextRegister);
}
-void InstructionSelection::loadQmlSingleton(const QString &name, IR::Temp *temp)
+void InstructionSelection::loadQmlSingleton(const QString &name, IR::Expr *temp)
{
generateFunctionCall(temp, Runtime::getQmlSingleton, Assembler::ContextRegister, Assembler::PointerToString(name));
}
-void InstructionSelection::loadConst(IR::Const *sourceConst, IR::Temp *targetTemp)
-{
- if (targetTemp->kind == IR::Temp::PhysicalRegister) {
- if (targetTemp->type == IR::DoubleType) {
- Q_ASSERT(sourceConst->type == IR::DoubleType);
- _as->toDoubleRegister(sourceConst, (Assembler::FPRegisterID) targetTemp->index);
- } else if (targetTemp->type == IR::SInt32Type) {
- Q_ASSERT(sourceConst->type == IR::SInt32Type);
- _as->toInt32Register(sourceConst, (Assembler::RegisterID) targetTemp->index);
- } else if (targetTemp->type == IR::UInt32Type) {
- Q_ASSERT(sourceConst->type == IR::UInt32Type);
- _as->toUInt32Register(sourceConst, (Assembler::RegisterID) targetTemp->index);
- } else if (targetTemp->type == IR::BoolType) {
- Q_ASSERT(sourceConst->type == IR::BoolType);
- _as->move(Assembler::TrustedImm32(convertToValue(sourceConst).int_32),
- (Assembler::RegisterID) targetTemp->index);
- } else {
- Q_UNREACHABLE();
+void InstructionSelection::loadConst(IR::Const *sourceConst, IR::Expr *target)
+{
+ if (IR::Temp *targetTemp = target->asTemp()) {
+ if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ if (targetTemp->type == IR::DoubleType) {
+ Q_ASSERT(sourceConst->type == IR::DoubleType);
+ _as->toDoubleRegister(sourceConst, (Assembler::FPRegisterID) targetTemp->index);
+ } else if (targetTemp->type == IR::SInt32Type) {
+ Q_ASSERT(sourceConst->type == IR::SInt32Type);
+ _as->toInt32Register(sourceConst, (Assembler::RegisterID) targetTemp->index);
+ } else if (targetTemp->type == IR::UInt32Type) {
+ Q_ASSERT(sourceConst->type == IR::UInt32Type);
+ _as->toUInt32Register(sourceConst, (Assembler::RegisterID) targetTemp->index);
+ } else if (targetTemp->type == IR::BoolType) {
+ Q_ASSERT(sourceConst->type == IR::BoolType);
+ _as->move(Assembler::TrustedImm32(convertToValue(sourceConst).int_32),
+ (Assembler::RegisterID) targetTemp->index);
+ } else {
+ Q_UNREACHABLE();
+ }
+ return;
}
- } else {
- _as->storeValue(convertToValue(sourceConst), targetTemp);
}
+
+ _as->storeValue(convertToValue(sourceConst), target);
}
-void InstructionSelection::loadString(const QString &str, IR::Temp *targetTemp)
+void InstructionSelection::loadString(const QString &str, IR::Expr *target)
{
Pointer srcAddr = _as->loadStringAddress(Assembler::ReturnValueRegister, str);
_as->loadPtr(srcAddr, Assembler::ReturnValueRegister);
- Pointer destAddr = _as->loadTempAddress(Assembler::ScratchRegister, targetTemp);
+ Pointer destAddr = _as->loadAddress(Assembler::ScratchRegister, target);
#if QT_POINTER_SIZE == 8
_as->store64(Assembler::ReturnValueRegister, destAddr);
#else
@@ -700,20 +703,20 @@ void InstructionSelection::loadString(const QString &str, IR::Temp *targetTemp)
#endif
}
-void InstructionSelection::loadRegexp(IR::RegExp *sourceRegexp, IR::Temp *targetTemp)
+void InstructionSelection::loadRegexp(IR::RegExp *sourceRegexp, IR::Expr *target)
{
int id = registerRegExp(sourceRegexp);
- generateFunctionCall(targetTemp, Runtime::regexpLiteral, Assembler::ContextRegister, Assembler::TrustedImm32(id));
+ generateFunctionCall(target, Runtime::regexpLiteral, Assembler::ContextRegister, Assembler::TrustedImm32(id));
}
-void InstructionSelection::getActivationProperty(const IR::Name *name, IR::Temp *temp)
+void InstructionSelection::getActivationProperty(const IR::Name *name, IR::Expr *target)
{
if (useFastLookups && name->global) {
uint index = registerGlobalGetterLookup(*name->id);
- generateLookupCall(temp, index, qOffsetOf(QV4::Lookup, globalGetter), Assembler::ContextRegister, Assembler::Void);
+ generateLookupCall(target, index, qOffsetOf(QV4::Lookup, globalGetter), Assembler::ContextRegister, Assembler::Void);
return;
}
- generateFunctionCall(temp, Runtime::getActivationProperty, Assembler::ContextRegister, Assembler::PointerToString(*name->id));
+ generateFunctionCall(target, Runtime::getActivationProperty, Assembler::ContextRegister, Assembler::PointerToString(*name->id));
}
void InstructionSelection::setActivationProperty(IR::Expr *source, const QString &targetName)
@@ -723,13 +726,13 @@ void InstructionSelection::setActivationProperty(IR::Expr *source, const QString
Assembler::ContextRegister, Assembler::PointerToString(targetName), Assembler::PointerToValue(source));
}
-void InstructionSelection::initClosure(IR::Closure *closure, IR::Temp *target)
+void InstructionSelection::initClosure(IR::Closure *closure, IR::Expr *target)
{
int id = closure->value;
generateFunctionCall(target, Runtime::closure, Assembler::ContextRegister, Assembler::TrustedImm32(id));
}
-void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR::Temp *target)
+void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR::Expr *target)
{
if (useFastLookups) {
uint index = registerGetterLookup(name);
@@ -740,7 +743,7 @@ void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR::
}
}
-void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Temp *target)
+void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Expr *target)
{
if (attachedPropertiesId != 0)
generateFunctionCall(target, Runtime::getQmlAttachedProperty, Assembler::ContextRegister, Assembler::TrustedImm32(attachedPropertiesId), Assembler::TrustedImm32(propertyIndex));
@@ -770,7 +773,7 @@ void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *target
Assembler::TrustedImm32(propertyIndex), Assembler::PointerToValue(source));
}
-void InstructionSelection::getElement(IR::Expr *base, IR::Expr *index, IR::Temp *target)
+void InstructionSelection::getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target)
{
if (useFastLookups) {
uint lookup = registerIndexedGetterLookup();
@@ -798,13 +801,20 @@ void InstructionSelection::setElement(IR::Expr *source, IR::Expr *targetBase, IR
Assembler::PointerToValue(source));
}
-void InstructionSelection::copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp)
+void InstructionSelection::copyValue(IR::Expr *source, IR::Expr *target)
{
- if (*sourceTemp == *targetTemp)
+ IR::Temp *sourceTemp = source->asTemp();
+ IR::Temp *targetTemp = target->asTemp();
+
+ if (sourceTemp && targetTemp && *sourceTemp == *targetTemp)
return;
+ if (IR::ArgLocal *sal = source->asArgLocal())
+ if (IR::ArgLocal *tal = target->asArgLocal())
+ if (*sal == *tal)
+ return;
- if (sourceTemp->kind == IR::Temp::PhysicalRegister) {
- if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ if (sourceTemp && sourceTemp->kind == IR::Temp::PhysicalRegister) {
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) {
if (sourceTemp->type == IR::DoubleType)
_as->moveDouble((Assembler::FPRegisterID) sourceTemp->index,
(Assembler::FPRegisterID) targetTemp->index);
@@ -815,16 +825,16 @@ void InstructionSelection::copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp)
} else {
switch (sourceTemp->type) {
case IR::DoubleType:
- _as->storeDouble((Assembler::FPRegisterID) sourceTemp->index, targetTemp);
+ _as->storeDouble((Assembler::FPRegisterID) sourceTemp->index, target);
break;
case IR::SInt32Type:
- _as->storeInt32((Assembler::RegisterID) sourceTemp->index, targetTemp);
+ _as->storeInt32((Assembler::RegisterID) sourceTemp->index, target);
break;
case IR::UInt32Type:
- _as->storeUInt32((Assembler::RegisterID) sourceTemp->index, targetTemp);
+ _as->storeUInt32((Assembler::RegisterID) sourceTemp->index, target);
break;
case IR::BoolType:
- _as->storeBool((Assembler::RegisterID) sourceTemp->index, targetTemp);
+ _as->storeBool((Assembler::RegisterID) sourceTemp->index, target);
break;
default:
Q_ASSERT(!"Unreachable");
@@ -832,23 +842,23 @@ void InstructionSelection::copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp)
}
return;
}
- } else if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ } else if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) {
switch (targetTemp->type) {
case IR::DoubleType:
- Q_ASSERT(sourceTemp->type == IR::DoubleType);
- _as->toDoubleRegister(sourceTemp, (Assembler::FPRegisterID) targetTemp->index);
+ Q_ASSERT(source->type == IR::DoubleType);
+ _as->toDoubleRegister(source, (Assembler::FPRegisterID) targetTemp->index);
return;
case IR::BoolType:
- Q_ASSERT(sourceTemp->type == IR::BoolType);
- _as->toInt32Register(sourceTemp, (Assembler::RegisterID) targetTemp->index);
+ Q_ASSERT(source->type == IR::BoolType);
+ _as->toInt32Register(source, (Assembler::RegisterID) targetTemp->index);
return;
case IR::SInt32Type:
- Q_ASSERT(sourceTemp->type == IR::SInt32Type);
- _as->toInt32Register(sourceTemp, (Assembler::RegisterID) targetTemp->index);
+ Q_ASSERT(source->type == IR::SInt32Type);
+ _as->toInt32Register(source, (Assembler::RegisterID) targetTemp->index);
return;
case IR::UInt32Type:
- Q_ASSERT(sourceTemp->type == IR::UInt32Type);
- _as->toUInt32Register(sourceTemp, (Assembler::RegisterID) targetTemp->index);
+ Q_ASSERT(source->type == IR::UInt32Type);
+ _as->toUInt32Register(source, (Assembler::RegisterID) targetTemp->index);
return;
default:
Q_ASSERT(!"Unreachable");
@@ -857,14 +867,16 @@ void InstructionSelection::copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp)
}
// The target is not a physical register, nor is the source. So we can do a memory-to-memory copy:
- _as->memcopyValue(_as->loadTempAddress(Assembler::ReturnValueRegister, targetTemp), sourceTemp,
- Assembler::ScratchRegister);
+ _as->memcopyValue(_as->loadAddress(Assembler::ReturnValueRegister, target), source, Assembler::ScratchRegister);
}
-void InstructionSelection::swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp)
+void InstructionSelection::swapValues(IR::Expr *source, IR::Expr *target)
{
- if (sourceTemp->kind == IR::Temp::PhysicalRegister) {
- if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ IR::Temp *sourceTemp = source->asTemp();
+ IR::Temp *targetTemp = target->asTemp();
+
+ if (sourceTemp && sourceTemp->kind == IR::Temp::PhysicalRegister) {
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) {
Q_ASSERT(sourceTemp->type == targetTemp->type);
if (sourceTemp->type == IR::DoubleType) {
@@ -878,11 +890,11 @@ void InstructionSelection::swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp
}
return;
}
- } else if (sourceTemp->kind == IR::Temp::StackSlot) {
- if (targetTemp->kind == IR::Temp::StackSlot) {
+ } else if (!sourceTemp || sourceTemp->kind == IR::Temp::StackSlot) {
+ if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) {
// Note: a swap for two stack-slots can involve different types.
- Assembler::Pointer sAddr = _as->stackSlotPointer(sourceTemp);
- Assembler::Pointer tAddr = _as->stackSlotPointer(targetTemp);
+ Assembler::Pointer sAddr = _as->loadAddress(Assembler::ScratchRegister, source);
+ Assembler::Pointer tAddr = _as->loadAddress(Assembler::ReturnValueRegister, target);
// use the implementation in JSC::MacroAssembler, as it doesn't do bit swizzling
_as->JSC::MacroAssembler::loadDouble(sAddr, Assembler::FPGpr0);
_as->JSC::MacroAssembler::loadDouble(tAddr, Assembler::FPGpr1);
@@ -892,25 +904,28 @@ void InstructionSelection::swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp
}
}
- IR::Temp *stackTemp = sourceTemp->kind == IR::Temp::StackSlot ? sourceTemp : targetTemp;
- IR::Temp *registerTemp = sourceTemp->kind == IR::Temp::PhysicalRegister ? sourceTemp
- : targetTemp;
- Assembler::Pointer addr = _as->stackSlotPointer(stackTemp);
- if (registerTemp->type == IR::DoubleType) {
+ IR::Expr *memExpr = !sourceTemp || sourceTemp->kind == IR::Temp::StackSlot ? source : target;
+ IR::Temp *regTemp = sourceTemp && sourceTemp->kind == IR::Temp::PhysicalRegister ? sourceTemp
+ : targetTemp;
+ Q_ASSERT(memExpr);
+ Q_ASSERT(regTemp);
+
+ Assembler::Pointer addr = _as->loadAddress(Assembler::ReturnValueRegister, memExpr);
+ if (regTemp->type == IR::DoubleType) {
_as->loadDouble(addr, Assembler::FPGpr0);
- _as->storeDouble((Assembler::FPRegisterID) registerTemp->index, addr);
- _as->moveDouble(Assembler::FPGpr0, (Assembler::FPRegisterID) registerTemp->index);
- } else if (registerTemp->type == IR::UInt32Type) {
+ _as->storeDouble((Assembler::FPRegisterID) regTemp->index, addr);
+ _as->moveDouble(Assembler::FPGpr0, (Assembler::FPRegisterID) regTemp->index);
+ } else if (regTemp->type == IR::UInt32Type) {
_as->toUInt32Register(addr, Assembler::ScratchRegister);
- _as->storeUInt32((Assembler::RegisterID) registerTemp->index, addr);
- _as->move(Assembler::ScratchRegister, (Assembler::RegisterID) registerTemp->index);
+ _as->storeUInt32((Assembler::RegisterID) regTemp->index, addr);
+ _as->move(Assembler::ScratchRegister, (Assembler::RegisterID) regTemp->index);
} else {
_as->load32(addr, Assembler::ScratchRegister);
- _as->store32((Assembler::RegisterID) registerTemp->index, addr);
- if (registerTemp->type != stackTemp->type) {
+ _as->store32((Assembler::RegisterID) regTemp->index, addr);
+ if (regTemp->type != memExpr->type) {
addr.offset += 4;
quint32 tag;
- switch (registerTemp->type) {
+ switch (regTemp->type) {
case IR::BoolType:
tag = QV4::Value::_Boolean_Type;
break;
@@ -923,7 +938,7 @@ void InstructionSelection::swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp
}
_as->store32(Assembler::TrustedImm32(tag), addr);
}
- _as->move(Assembler::ScratchRegister, (Assembler::RegisterID) registerTemp->index);
+ _as->move(Assembler::ScratchRegister, (Assembler::RegisterID) regTemp->index);
}
}
@@ -932,21 +947,21 @@ void InstructionSelection::swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp
#define setOpContext(op, opName, operation) \
do { opContext = operation; opName = isel_stringIfy(operation); } while (0)
-void InstructionSelection::unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *targetTemp)
+void InstructionSelection::unop(IR::AluOp oper, IR::Expr *source, IR::Expr *target)
{
QV4::JIT::Unop unop(_as, oper);
- unop.generate(sourceTemp, targetTemp);
+ unop.generate(source, target);
}
-void InstructionSelection::binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target)
+void InstructionSelection::binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target)
{
QV4::JIT::Binop binop(_as, oper);
binop.generate(leftSource, rightSource, target);
}
void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR::ExprList *args,
- IR::Temp *result)
+ IR::Expr *result)
{
Q_ASSERT(base != 0);
@@ -966,7 +981,7 @@ void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR:
}
void InstructionSelection::callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args,
- IR::Temp *result)
+ IR::Expr *result)
{
Q_ASSERT(base != 0);
@@ -976,7 +991,7 @@ void InstructionSelection::callSubscript(IR::Expr *base, IR::Expr *index, IR::Ex
baseAddressForCallData());
}
-void InstructionSelection::convertType(IR::Temp *source, IR::Temp *target)
+void InstructionSelection::convertType(IR::Expr *source, IR::Expr *target)
{
switch (target->type) {
case IR::DoubleType:
@@ -997,7 +1012,7 @@ void InstructionSelection::convertType(IR::Temp *source, IR::Temp *target)
}
}
-void InstructionSelection::convertTypeSlowPath(IR::Temp *source, IR::Temp *target)
+void InstructionSelection::convertTypeSlowPath(IR::Expr *source, IR::Expr *target)
{
Q_ASSERT(target->type != IR::BoolType);
@@ -1007,7 +1022,7 @@ void InstructionSelection::convertTypeSlowPath(IR::Temp *source, IR::Temp *targe
copyValue(source, target);
}
-void InstructionSelection::convertTypeToDouble(IR::Temp *source, IR::Temp *target)
+void InstructionSelection::convertTypeToDouble(IR::Expr *source, IR::Expr *target)
{
switch (source->type) {
case IR::SInt32Type:
@@ -1019,13 +1034,13 @@ void InstructionSelection::convertTypeToDouble(IR::Temp *source, IR::Temp *targe
convertUIntToDouble(source, target);
break;
case IR::UndefinedType:
- _as->loadDouble(_as->loadTempAddress(Assembler::ScratchRegister, source), Assembler::FPGpr0);
+ _as->loadDouble(_as->loadAddress(Assembler::ScratchRegister, source), Assembler::FPGpr0);
_as->storeDouble(Assembler::FPGpr0, target);
break;
case IR::StringType:
case IR::VarType: {
// load the tag:
- Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ Assembler::Pointer tagAddr = _as->loadAddress(Assembler::ScratchRegister, source);
tagAddr.offset += 4;
_as->load32(tagAddr, Assembler::ScratchRegister);
@@ -1052,17 +1067,18 @@ void InstructionSelection::convertTypeToDouble(IR::Temp *source, IR::Temp *targe
// it is a double:
isDbl.link(_as);
- Assembler::Pointer addr2 = _as->loadTempAddress(Assembler::ScratchRegister, source);
- if (target->kind == IR::Temp::StackSlot) {
+ Assembler::Pointer addr2 = _as->loadAddress(Assembler::ScratchRegister, source);
+ IR::Temp *targetTemp = target->asTemp();
+ if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) {
#if QT_POINTER_SIZE == 8
_as->load64(addr2, Assembler::ScratchRegister);
- _as->store64(Assembler::ScratchRegister, _as->stackSlotPointer(target));
+ _as->store64(Assembler::ScratchRegister, _as->loadAddress(Assembler::ReturnValueRegister, target));
#else
_as->loadDouble(addr2, Assembler::FPGpr0);
- _as->storeDouble(Assembler::FPGpr0, _as->stackSlotPointer(target));
+ _as->storeDouble(Assembler::FPGpr0, _as->loadAddress(Assembler::ReturnValueRegister, target));
#endif
} else {
- _as->loadDouble(addr2, (Assembler::FPRegisterID) target->index);
+ _as->loadDouble(addr2, (Assembler::FPRegisterID) targetTemp->index);
}
noDoubleDone.link(_as);
@@ -1074,8 +1090,9 @@ void InstructionSelection::convertTypeToDouble(IR::Temp *source, IR::Temp *targe
}
}
-void InstructionSelection::convertTypeToBool(IR::Temp *source, IR::Temp *target)
+void InstructionSelection::convertTypeToBool(IR::Expr *source, IR::Expr *target)
{
+ IR::Temp *sourceTemp = source->asTemp();
switch (source->type) {
case IR::SInt32Type:
case IR::UInt32Type:
@@ -1086,8 +1103,8 @@ void InstructionSelection::convertTypeToBool(IR::Temp *source, IR::Temp *target)
// allocator was not used, then that means that we can use any register for to
// load the double into.
Assembler::FPRegisterID reg;
- if (source->kind == IR::Temp::PhysicalRegister)
- reg = (Assembler::FPRegisterID) source->index;
+ if (sourceTemp && sourceTemp->kind == IR::Temp::PhysicalRegister)
+ reg = (Assembler::FPRegisterID) sourceTemp->index;
else
reg = _as->toDoubleRegister(source, (Assembler::FPRegisterID) 1);
Assembler::Jump nonZero = _as->branchDoubleNonZero(reg, Assembler::FPGpr0);
@@ -1117,13 +1134,13 @@ void InstructionSelection::convertTypeToBool(IR::Temp *source, IR::Temp *target)
}
}
-void InstructionSelection::convertTypeToSInt32(IR::Temp *source, IR::Temp *target)
+void InstructionSelection::convertTypeToSInt32(IR::Expr *source, IR::Expr *target)
{
switch (source->type) {
case IR::VarType: {
#if QT_POINTER_SIZE == 8
- Assembler::Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ Assembler::Pointer addr = _as->loadAddress(Assembler::ScratchRegister, source);
_as->load64(addr, Assembler::ScratchRegister);
_as->move(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
@@ -1143,12 +1160,13 @@ void InstructionSelection::convertTypeToSInt32(IR::Temp *source, IR::Temp *targe
// not an int:
fallback.link(_as);
generateFunctionCall(Assembler::ReturnValueRegister, Runtime::toInt,
- _as->loadTempAddress(Assembler::ScratchRegister, source));
+ _as->loadAddress(Assembler::ScratchRegister, source));
isInt.link(_as);
success.link(_as);
- if (target->kind == IR::Temp::StackSlot) {
- Assembler::Pointer targetAddr = _as->stackSlotPointer(target);
+ IR::Temp *targetTemp = target->asTemp();
+ if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) {
+ Assembler::Pointer targetAddr = _as->loadAddress(Assembler::ScratchRegister, target);
_as->store32(Assembler::ReturnValueRegister, targetAddr);
targetAddr.offset += 4;
_as->store32(Assembler::TrustedImm32(Value::_Integer_Type), targetAddr);
@@ -1157,7 +1175,7 @@ void InstructionSelection::convertTypeToSInt32(IR::Temp *source, IR::Temp *targe
}
#else
// load the tag:
- Assembler::Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ Assembler::Pointer addr = _as->loadAddress(Assembler::ScratchRegister, source);
Assembler::Pointer tagAddr = addr;
tagAddr.offset += 4;
_as->load32(tagAddr, Assembler::ReturnValueRegister);
@@ -1165,21 +1183,22 @@ void InstructionSelection::convertTypeToSInt32(IR::Temp *source, IR::Temp *targe
// check if it's an int32:
Assembler::Jump fallback = _as->branch32(Assembler::NotEqual, Assembler::ReturnValueRegister,
Assembler::TrustedImm32(Value::_Integer_Type));
- if (target->kind == IR::Temp::StackSlot) {
- _as->load32(addr, Assembler::ScratchRegister);
- Assembler::Pointer targetAddr = _as->stackSlotPointer(target);
- _as->store32(Assembler::ScratchRegister, targetAddr);
+ IR::Temp *targetTemp = target->asTemp();
+ if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) {
+ _as->load32(addr, Assembler::ReturnValueRegister);
+ Assembler::Pointer targetAddr = _as->loadAddress(Assembler::ScratchRegister, target);
+ _as->store32(Assembler::ReturnValueRegister, targetAddr);
targetAddr.offset += 4;
_as->store32(Assembler::TrustedImm32(Value::_Integer_Type), targetAddr);
} else {
- _as->load32(addr, (Assembler::RegisterID) target->index);
+ _as->load32(addr, (Assembler::RegisterID) targetTemp->index);
}
Assembler::Jump intDone = _as->jump();
// not an int:
fallback.link(_as);
generateFunctionCall(Assembler::ReturnValueRegister, Runtime::toInt,
- _as->loadTempAddress(Assembler::ScratchRegister, source));
+ _as->loadAddress(Assembler::ScratchRegister, source));
_as->storeInt32(Assembler::ReturnValueRegister, target);
intDone.link(_as);
@@ -1210,32 +1229,32 @@ void InstructionSelection::convertTypeToSInt32(IR::Temp *source, IR::Temp *targe
case IR::StringType:
default:
generateFunctionCall(Assembler::ReturnValueRegister, Runtime::toInt,
- _as->loadTempAddress(Assembler::ScratchRegister, source));
+ _as->loadAddress(Assembler::ScratchRegister, source));
_as->storeInt32(Assembler::ReturnValueRegister, target);
break;
} // switch (source->type)
}
-void InstructionSelection::convertTypeToUInt32(IR::Temp *source, IR::Temp *target)
+void InstructionSelection::convertTypeToUInt32(IR::Expr *source, IR::Expr *target)
{
switch (source->type) {
case IR::VarType: {
// load the tag:
- Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ Assembler::Pointer tagAddr = _as->loadAddress(Assembler::ScratchRegister, source);
tagAddr.offset += 4;
_as->load32(tagAddr, Assembler::ScratchRegister);
// check if it's an int32:
Assembler::Jump isNoInt = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
Assembler::TrustedImm32(Value::_Integer_Type));
- Assembler::Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ Assembler::Pointer addr = _as->loadAddress(Assembler::ScratchRegister, source);
_as->storeUInt32(_as->toInt32Register(addr, Assembler::ScratchRegister), target);
Assembler::Jump intDone = _as->jump();
// not an int:
isNoInt.link(_as);
generateFunctionCall(Assembler::ReturnValueRegister, Runtime::toUInt,
- _as->loadTempAddress(Assembler::ScratchRegister, source));
+ _as->loadAddress(Assembler::ScratchRegister, source));
_as->storeInt32(Assembler::ReturnValueRegister, target);
intDone.link(_as);
@@ -1269,7 +1288,7 @@ void InstructionSelection::convertTypeToUInt32(IR::Temp *source, IR::Temp *targe
} // switch (source->type)
}
-void InstructionSelection::constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Temp *result)
+void InstructionSelection::constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Expr *result)
{
Q_ASSERT(func != 0);
prepareCallData(args, 0);
@@ -1289,7 +1308,7 @@ void InstructionSelection::constructActivationProperty(IR::Name *func, IR::ExprL
}
-void InstructionSelection::constructProperty(IR::Temp *base, const QString &name, IR::ExprList *args, IR::Temp *result)
+void InstructionSelection::constructProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result)
{
prepareCallData(args, base);
if (useFastLookups) {
@@ -1306,7 +1325,7 @@ void InstructionSelection::constructProperty(IR::Temp *base, const QString &name
baseAddressForCallData());
}
-void InstructionSelection::constructValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result)
+void InstructionSelection::constructValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result)
{
Q_ASSERT(value != 0);
@@ -1325,16 +1344,17 @@ void InstructionSelection::visitJump(IR::Jump *s)
void InstructionSelection::visitCJump(IR::CJump *s)
{
- if (IR::Temp *t = s->cond->asTemp()) {
+ IR::Temp *t = s->cond->asTemp();
+ if (t || s->cond->asArgLocal()) {
Assembler::RegisterID reg;
- if (t->kind == IR::Temp::PhysicalRegister) {
+ if (t && t->kind == IR::Temp::PhysicalRegister) {
Q_ASSERT(t->type == IR::BoolType);
reg = (Assembler::RegisterID) t->index;
- } else if (t->kind == IR::Temp::StackSlot && t->type == IR::BoolType) {
+ } else if (t && t->kind == IR::Temp::StackSlot && t->type == IR::BoolType) {
reg = Assembler::ReturnValueRegister;
_as->toInt32Register(t, reg);
} else {
- Address temp = _as->loadTempAddress(Assembler::ScratchRegister, t);
+ Address temp = _as->loadAddress(Assembler::ScratchRegister, s->cond);
Address tag = temp;
tag.offset += qOffsetOf(QV4::Value, tag);
Assembler::Jump booleanConversion = _as->branch32(Assembler::NotEqual, tag, Assembler::TrustedImm32(QV4::Value::Boolean_Type));
@@ -1346,7 +1366,7 @@ void InstructionSelection::visitCJump(IR::CJump *s)
booleanConversion.link(_as);
reg = Assembler::ReturnValueRegister;
- generateFunctionCall(reg, Runtime::toBoolean, Assembler::Reference(t));
+ generateFunctionCall(reg, Runtime::toBoolean, Assembler::Reference(s->cond));
testBoolean.link(_as);
}
@@ -1456,7 +1476,7 @@ void InstructionSelection::visitRet(IR::Ret *s)
Q_UNREACHABLE();
}
} else {
- Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, t);
+ Pointer addr = _as->loadAddress(Assembler::ScratchRegister, t);
_as->load32(addr, lowReg);
addr.offset += 4;
_as->load32(addr, highReg);
@@ -1693,10 +1713,7 @@ bool InstructionSelection::visitCJumpStrictNullUndefined(IR::Type nullOrUndef, I
return true;
}
- IR::Temp *t = varSrc->asTemp();
- Q_ASSERT(t);
-
- Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, t);
+ Assembler::Pointer tagAddr = _as->loadAddress(Assembler::ScratchRegister, varSrc);
tagAddr.offset += 4;
const Assembler::RegisterID tagReg = Assembler::ScratchRegister;
_as->load32(tagAddr, tagReg);
@@ -1739,11 +1756,7 @@ bool InstructionSelection::visitCJumpStrictBool(IR::Binop *binop, IR::BasicBlock
return true;
}
- IR::Temp *otherTemp = otherSrc->asTemp();
- Q_ASSERT(otherTemp); // constants cannot have "var" type
- Q_ASSERT(otherTemp->kind != IR::Temp::PhysicalRegister);
-
- Assembler::Pointer otherAddr = _as->loadTempAddress(Assembler::ReturnValueRegister, otherTemp);
+ Assembler::Pointer otherAddr = _as->loadAddress(Assembler::ReturnValueRegister, otherSrc);
otherAddr.offset += 4; // tag address
// check if the tag of the var operand is indicates 'boolean'
@@ -1791,10 +1804,7 @@ bool InstructionSelection::visitCJumpNullUndefined(IR::Type nullOrUndef, IR::Bin
return true;
}
- IR::Temp *t = varSrc->asTemp();
- Q_ASSERT(t);
-
- Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, t);
+ Assembler::Pointer tagAddr = _as->loadAddress(Assembler::ScratchRegister, varSrc);
tagAddr.offset += 4;
const Assembler::RegisterID tagReg = Assembler::ScratchRegister;
_as->load32(tagAddr, tagReg);
diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h
index d589223d7e..83d2464ef3 100644
--- a/src/qml/jit/qv4isel_masm_p.h
+++ b/src/qml/jit/qv4isel_masm_p.h
@@ -76,54 +76,54 @@ public:
protected:
virtual QV4::CompiledData::CompilationUnit *backendCompileStep();
- virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Temp *result);
- virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Temp *result);
- virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Temp *result);
- virtual void callBuiltinTypeofName(const QString &name, IR::Temp *result);
- virtual void callBuiltinTypeofValue(IR::Expr *value, IR::Temp *result);
- virtual void callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result);
- virtual void callBuiltinDeleteSubscript(IR::Temp *base, IR::Expr *index, IR::Temp *result);
- virtual void callBuiltinDeleteName(const QString &name, IR::Temp *result);
- virtual void callBuiltinDeleteValue(IR::Temp *result);
+ virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result);
+ virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Expr *result);
+ virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Expr *result);
+ virtual void callBuiltinTypeofName(const QString &name, IR::Expr *result);
+ virtual void callBuiltinTypeofValue(IR::Expr *value, IR::Expr *result);
+ virtual void callBuiltinDeleteMember(IR::Expr *base, const QString &name, IR::Expr *result);
+ virtual void callBuiltinDeleteSubscript(IR::Expr *base, IR::Expr *index, IR::Expr *result);
+ virtual void callBuiltinDeleteName(const QString &name, IR::Expr *result);
+ virtual void callBuiltinDeleteValue(IR::Expr *result);
virtual void callBuiltinThrow(IR::Expr *arg);
virtual void callBuiltinReThrow();
- virtual void callBuiltinUnwindException(IR::Temp *);
+ virtual void callBuiltinUnwindException(IR::Expr *);
virtual void callBuiltinPushCatchScope(const QString &exceptionName);
- virtual void callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Temp *result);
- virtual void callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result);
- virtual void callBuiltinPushWithScope(IR::Temp *arg);
+ virtual void callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Expr *result);
+ virtual void callBuiltinForeachNextPropertyname(IR::Expr *arg, IR::Expr *result);
+ virtual void callBuiltinPushWithScope(IR::Expr *arg);
virtual void callBuiltinPopScope();
virtual void callBuiltinDeclareVar(bool deletable, const QString &name);
- virtual void callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args);
- virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray);
- virtual void callBuiltinSetupArgumentObject(IR::Temp *result);
+ virtual void callBuiltinDefineArray(IR::Expr *result, IR::ExprList *args);
+ virtual void callBuiltinDefineObjectLiteral(IR::Expr *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray);
+ virtual void callBuiltinSetupArgumentObject(IR::Expr *result);
virtual void callBuiltinConvertThisToObject();
- virtual void callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result);
- virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Temp *result);
- virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Temp *result);
- virtual void convertType(IR::Temp *source, IR::Temp *target);
- virtual void loadThisObject(IR::Temp *temp);
- virtual void loadQmlIdArray(IR::Temp *temp);
- virtual void loadQmlImportedScripts(IR::Temp *temp);
- virtual void loadQmlContextObject(IR::Temp *temp);
- virtual void loadQmlScopeObject(IR::Temp *temp);
- virtual void loadQmlSingleton(const QString &name, IR::Temp *temp);
- virtual void loadConst(IR::Const *sourceConst, IR::Temp *targetTemp);
- virtual void loadString(const QString &str, IR::Temp *targetTemp);
- virtual void loadRegexp(IR::RegExp *sourceRegexp, IR::Temp *targetTemp);
- virtual void getActivationProperty(const IR::Name *name, IR::Temp *temp);
+ virtual void callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result);
+ virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result);
+ virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Expr *result);
+ virtual void convertType(IR::Expr *source, IR::Expr *target);
+ virtual void loadThisObject(IR::Expr *temp);
+ virtual void loadQmlIdArray(IR::Expr *target);
+ virtual void loadQmlImportedScripts(IR::Expr *target);
+ virtual void loadQmlContextObject(IR::Expr *target);
+ virtual void loadQmlScopeObject(IR::Expr *target);
+ virtual void loadQmlSingleton(const QString &name, IR::Expr *target);
+ virtual void loadConst(IR::Const *sourceConst, IR::Expr *target);
+ virtual void loadString(const QString &str, IR::Expr *target);
+ virtual void loadRegexp(IR::RegExp *sourceRegexp, IR::Expr *target);
+ virtual void getActivationProperty(const IR::Name *name, IR::Expr *target);
virtual void setActivationProperty(IR::Expr *source, const QString &targetName);
- virtual void initClosure(IR::Closure *closure, IR::Temp *target);
- virtual void getProperty(IR::Expr *base, const QString &name, IR::Temp *target);
+ virtual void initClosure(IR::Closure *closure, IR::Expr *target);
+ virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target);
+ virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Expr *target);
virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName);
virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex);
- virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Temp *target);
- virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Temp *target);
+ virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target);
virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex);
- virtual void copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp);
- virtual void swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp);
- virtual void unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *targetTemp);
- virtual void binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target);
+ virtual void copyValue(IR::Expr *source, IR::Expr *target);
+ virtual void swapValues(IR::Expr *source, IR::Expr *target);
+ virtual void unop(IR::AluOp oper, IR::Expr *sourceTemp, IR::Expr *target);
+ virtual void binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target);
typedef Assembler::Address Address;
typedef Assembler::Pointer Pointer;
@@ -148,9 +148,9 @@ protected:
return _as->stackLayout().callDataAddress();
}
- virtual void constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Temp *result);
- virtual void constructProperty(IR::Temp *base, const QString &name, IR::ExprList *args, IR::Temp *result);
- virtual void constructValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result);
+ virtual void constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Expr *result);
+ virtual void constructProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr*result);
+ virtual void constructValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result);
virtual void visitJump(IR::Jump *);
virtual void visitCJump(IR::CJump *);
@@ -167,44 +167,51 @@ protected:
void visitCJumpEqual(IR::Binop *binop, IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock);
private:
- void convertTypeSlowPath(IR::Temp *source, IR::Temp *target);
- void convertTypeToDouble(IR::Temp *source, IR::Temp *target);
- void convertTypeToBool(IR::Temp *source, IR::Temp *target);
- void convertTypeToSInt32(IR::Temp *source, IR::Temp *target);
- void convertTypeToUInt32(IR::Temp *source, IR::Temp *target);
+ void convertTypeSlowPath(IR::Expr *source, IR::Expr *target);
+ void convertTypeToDouble(IR::Expr *source, IR::Expr *target);
+ void convertTypeToBool(IR::Expr *source, IR::Expr *target);
+ void convertTypeToSInt32(IR::Expr *source, IR::Expr *target);
+ void convertTypeToUInt32(IR::Expr *source, IR::Expr *target);
- void convertIntToDouble(IR::Temp *source, IR::Temp *target)
+ void convertIntToDouble(IR::Expr *source, IR::Expr *target)
{
- if (target->kind == IR::Temp::PhysicalRegister) {
- _as->convertInt32ToDouble(_as->toInt32Register(source, Assembler::ScratchRegister),
- (Assembler::FPRegisterID) target->index);
- } else {
- _as->convertInt32ToDouble(_as->toInt32Register(source, Assembler::ScratchRegister),
- Assembler::FPGpr0);
- _as->storeDouble(Assembler::FPGpr0, _as->stackSlotPointer(target));
+ if (IR::Temp *targetTemp = target->asTemp()) {
+ if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ _as->convertInt32ToDouble(_as->toInt32Register(source, Assembler::ScratchRegister),
+ (Assembler::FPRegisterID) targetTemp->index);
+ return;
+ }
}
+
+ _as->convertInt32ToDouble(_as->toInt32Register(source, Assembler::ScratchRegister),
+ Assembler::FPGpr0);
+ _as->storeDouble(Assembler::FPGpr0, _as->loadAddress(Assembler::ScratchRegister, target));
}
- void convertUIntToDouble(IR::Temp *source, IR::Temp *target)
+ void convertUIntToDouble(IR::Expr *source, IR::Expr *target)
{
Assembler::RegisterID tmpReg = Assembler::ScratchRegister;
Assembler::RegisterID reg = _as->toInt32Register(source, tmpReg);
- if (target->kind == IR::Temp::PhysicalRegister) {
- _as->convertUInt32ToDouble(reg, (Assembler::FPRegisterID) target->index, tmpReg);
- } else {
- _as->convertUInt32ToDouble(_as->toUInt32Register(source, tmpReg),
- Assembler::FPGpr0, tmpReg);
- _as->storeDouble(Assembler::FPGpr0, _as->stackSlotPointer(target));
+ if (IR::Temp *targetTemp = target->asTemp()) {
+ if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ _as->convertUInt32ToDouble(reg, (Assembler::FPRegisterID) targetTemp->index, tmpReg);
+ return;
+ }
}
+
+ _as->convertUInt32ToDouble(_as->toUInt32Register(source, tmpReg),
+ Assembler::FPGpr0, tmpReg);
+ _as->storeDouble(Assembler::FPGpr0, _as->loadAddress(tmpReg, target));
}
- void convertIntToBool(IR::Temp *source, IR::Temp *target)
+ void convertIntToBool(IR::Expr *source, IR::Expr *target)
{
- Assembler::RegisterID reg = target->kind == IR::Temp::PhysicalRegister
- ? (Assembler::RegisterID) target->index
- : Assembler::ScratchRegister;
+ Assembler::RegisterID reg = Assembler::ScratchRegister;
+ if (IR::Temp *targetTemp = target->asTemp())
+ if (targetTemp->kind == IR::Temp::PhysicalRegister)
+ reg = (Assembler::RegisterID) targetTemp->index;
_as->move(_as->toInt32Register(source, reg), reg);
_as->compare32(Assembler::NotEqual, reg, Assembler::TrustedImm32(0), reg);
_as->storeBool(reg, target);
diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp
index a66eab005f..331af3d635 100644
--- a/src/qml/jit/qv4regalloc.cpp
+++ b/src/qml/jit/qv4regalloc.cpp
@@ -139,7 +139,7 @@ public:
void addHint(const Temp &t, int physicalRegister)
{
Temp hint;
- hint.init(Temp::PhysicalRegister, physicalRegister, 0);
+ hint.init(Temp::PhysicalRegister, physicalRegister);
_hints[t].append(hint);
}
@@ -196,40 +196,41 @@ public:
}
protected: // IRDecoder
- virtual void callBuiltinInvalid(IR::Name *, IR::ExprList *, IR::Temp *) {}
- virtual void callBuiltinTypeofMember(IR::Expr *, const QString &, IR::Temp *) {}
- virtual void callBuiltinTypeofSubscript(IR::Expr *, IR::Expr *, IR::Temp *) {}
- virtual void callBuiltinTypeofName(const QString &, IR::Temp *) {}
- virtual void callBuiltinTypeofValue(IR::Expr *, IR::Temp *) {}
- virtual void callBuiltinDeleteMember(IR::Temp *, const QString &, IR::Temp *) {}
- virtual void callBuiltinDeleteSubscript(IR::Temp *, IR::Expr *, IR::Temp *) {}
- virtual void callBuiltinDeleteName(const QString &, IR::Temp *) {}
- virtual void callBuiltinDeleteValue(IR::Temp *) {}
+ virtual void callBuiltinInvalid(IR::Name *, IR::ExprList *, IR::Expr *) {}
+ virtual void callBuiltinTypeofMember(IR::Expr *, const QString &, IR::Expr *) {}
+ virtual void callBuiltinTypeofSubscript(IR::Expr *, IR::Expr *, IR::Expr *) {}
+ virtual void callBuiltinTypeofName(const QString &, IR::Expr *) {}
+ virtual void callBuiltinTypeofValue(IR::Expr *, IR::Expr *) {}
+ virtual void callBuiltinDeleteMember(IR::Expr *, const QString &, IR::Expr *) {}
+ virtual void callBuiltinDeleteSubscript(IR::Expr *, IR::Expr *, IR::Expr *) {}
+ virtual void callBuiltinDeleteName(const QString &, IR::Expr *) {}
+ virtual void callBuiltinDeleteValue(IR::Expr *) {}
virtual void callBuiltinThrow(IR::Expr *) {}
virtual void callBuiltinReThrow() {}
- virtual void callBuiltinUnwindException(IR::Temp *) {}
+ virtual void callBuiltinUnwindException(IR::Expr *) {}
virtual void callBuiltinPushCatchScope(const QString &) {};
- virtual void callBuiltinForeachIteratorObject(IR::Expr *, IR::Temp *) {}
+ virtual void callBuiltinForeachIteratorObject(IR::Expr *, IR::Expr *) {}
virtual void callBuiltinForeachNextProperty(IR::Temp *, IR::Temp *) {}
- virtual void callBuiltinForeachNextPropertyname(IR::Temp *, IR::Temp *) {}
- virtual void callBuiltinPushWithScope(IR::Temp *) {}
+ virtual void callBuiltinForeachNextPropertyname(IR::Expr *, IR::Expr *) {}
+ virtual void callBuiltinPushWithScope(IR::Expr *) {}
virtual void callBuiltinPopScope() {}
virtual void callBuiltinDeclareVar(bool , const QString &) {}
- virtual void callBuiltinDefineArray(IR::Temp *, IR::ExprList *) {}
- virtual void callBuiltinDefineObjectLiteral(IR::Temp *, int, IR::ExprList *, IR::ExprList *, bool) {}
- virtual void callBuiltinSetupArgumentObject(IR::Temp *) {}
+ virtual void callBuiltinDefineArray(IR::Expr *, IR::ExprList *) {}
+ virtual void callBuiltinDefineObjectLiteral(IR::Expr *, int, IR::ExprList *, IR::ExprList *, bool) {}
+ virtual void callBuiltinSetupArgumentObject(IR::Expr *) {}
virtual void callBuiltinConvertThisToObject() {}
- virtual void callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result)
+ virtual void callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result)
{
addDef(result);
- addUses(value, Use::CouldHaveRegister);
+ if (IR::Temp *tempValue = value->asTemp())
+ addUses(tempValue, Use::CouldHaveRegister);
addUses(args, Use::CouldHaveRegister);
addCall();
}
virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args,
- IR::Temp *result)
+ IR::Expr *result)
{
Q_UNUSED(name)
@@ -240,7 +241,7 @@ protected: // IRDecoder
}
virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args,
- IR::Temp *result)
+ IR::Expr *result)
{
addDef(result);
addUses(base->asTemp(), Use::CouldHaveRegister);
@@ -249,7 +250,7 @@ protected: // IRDecoder
addCall();
}
- virtual void convertType(IR::Temp *source, IR::Temp *target)
+ virtual void convertType(IR::Expr *source, IR::Expr *target)
{
addDef(target);
@@ -312,22 +313,24 @@ protected: // IRDecoder
break;
}
- addUses(source, sourceReg);
+ Temp *sourceTemp = source->asTemp();
+ if (sourceTemp)
+ addUses(sourceTemp, sourceReg);
if (needsCall)
addCall();
- else
- addHint(target, source);
+ else if (target->asTemp())
+ addHint(target->asTemp(), sourceTemp);
}
- virtual void constructActivationProperty(IR::Name *, IR::ExprList *args, IR::Temp *result)
+ virtual void constructActivationProperty(IR::Name *, IR::ExprList *args, IR::Expr *result)
{
addDef(result);
addUses(args, Use::CouldHaveRegister);
addCall();
}
- virtual void constructProperty(IR::Temp *base, const QString &, IR::ExprList *args, IR::Temp *result)
+ virtual void constructProperty(IR::Expr *base, const QString &, IR::ExprList *args, IR::Expr *result)
{
addDef(result);
addUses(base, Use::CouldHaveRegister);
@@ -335,7 +338,7 @@ protected: // IRDecoder
addCall();
}
- virtual void constructValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result)
+ virtual void constructValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result)
{
addDef(result);
addUses(value, Use::CouldHaveRegister);
@@ -343,30 +346,30 @@ protected: // IRDecoder
addCall();
}
- virtual void loadThisObject(IR::Temp *temp)
+ virtual void loadThisObject(IR::Expr *temp)
{
addDef(temp);
}
- virtual void loadQmlIdArray(IR::Temp *temp)
+ virtual void loadQmlIdArray(IR::Expr *temp)
{
addDef(temp);
addCall();
}
- virtual void loadQmlImportedScripts(IR::Temp *temp)
+ virtual void loadQmlImportedScripts(IR::Expr *temp)
{
addDef(temp);
addCall();
}
- virtual void loadQmlContextObject(Temp *temp)
+ virtual void loadQmlContextObject(Expr *temp)
{
addDef(temp);
addCall();
}
- virtual void loadQmlScopeObject(Temp *temp)
+ virtual void loadQmlScopeObject(Expr *temp)
{
Q_UNUSED(temp);
@@ -374,7 +377,7 @@ protected: // IRDecoder
addCall();
}
- virtual void loadQmlSingleton(const QString &/*name*/, Temp *temp)
+ virtual void loadQmlSingleton(const QString &/*name*/, Expr *temp)
{
Q_UNUSED(temp);
@@ -382,21 +385,21 @@ protected: // IRDecoder
addCall();
}
- virtual void loadConst(IR::Const *sourceConst, IR::Temp *targetTemp)
+ virtual void loadConst(IR::Const *sourceConst, Expr *targetTemp)
{
Q_UNUSED(sourceConst);
addDef(targetTemp);
}
- virtual void loadString(const QString &str, IR::Temp *targetTemp)
+ virtual void loadString(const QString &str, Expr *targetTemp)
{
Q_UNUSED(str);
addDef(targetTemp);
}
- virtual void loadRegexp(IR::RegExp *sourceRegexp, IR::Temp *targetTemp)
+ virtual void loadRegexp(IR::RegExp *sourceRegexp, Expr *targetTemp)
{
Q_UNUSED(sourceRegexp);
@@ -404,7 +407,7 @@ protected: // IRDecoder
addCall();
}
- virtual void getActivationProperty(const IR::Name *, IR::Temp *temp)
+ virtual void getActivationProperty(const IR::Name *, Expr *temp)
{
addDef(temp);
addCall();
@@ -416,7 +419,7 @@ protected: // IRDecoder
addCall();
}
- virtual void initClosure(IR::Closure *closure, IR::Temp *target)
+ virtual void initClosure(IR::Closure *closure, Expr *target)
{
Q_UNUSED(closure);
@@ -424,7 +427,7 @@ protected: // IRDecoder
addCall();
}
- virtual void getProperty(IR::Expr *base, const QString &, IR::Temp *target)
+ virtual void getProperty(IR::Expr *base, const QString &, Expr *target)
{
addDef(target);
addUses(base->asTemp(), Use::CouldHaveRegister);
@@ -445,14 +448,14 @@ protected: // IRDecoder
addCall();
}
- virtual void getQObjectProperty(IR::Expr *base, int /*propertyIndex*/, bool /*captureRequired*/, int /*attachedPropertiesId*/, IR::Temp *target)
+ virtual void getQObjectProperty(IR::Expr *base, int /*propertyIndex*/, bool /*captureRequired*/, int /*attachedPropertiesId*/, IR::Expr *target)
{
addDef(target);
addUses(base->asTemp(), Use::CouldHaveRegister);
addCall();
}
- virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Temp *target)
+ virtual void getElement(IR::Expr *base, IR::Expr *index, Expr *target)
{
addDef(target);
addUses(base->asTemp(), Use::CouldHaveRegister);
@@ -468,25 +471,30 @@ protected: // IRDecoder
addCall();
}
- virtual void copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp)
+ virtual void copyValue(Expr *source, Expr *target)
{
- addDef(targetTemp);
+ addDef(target);
+ Temp *sourceTemp = source->asTemp();
+ if (!sourceTemp)
+ return;
addUses(sourceTemp, Use::CouldHaveRegister);
- addHint(targetTemp, sourceTemp);
+ Temp *targetTemp = target->asTemp();
+ if (targetTemp)
+ addHint(targetTemp, sourceTemp);
}
- virtual void swapValues(IR::Temp *, IR::Temp *)
+ virtual void swapValues(Expr *, Expr *)
{
// Inserted by the register allocator, so it cannot occur here.
Q_UNREACHABLE();
}
- virtual void unop(AluOp oper, Temp *sourceTemp, Temp *targetTemp)
+ virtual void unop(AluOp oper, Expr *source, Expr *target)
{
- addDef(targetTemp);
+ addDef(target);
bool needsCall = true;
- if (oper == OpNot && sourceTemp->type == IR::BoolType && targetTemp->type == IR::BoolType)
+ if (oper == OpNot && source->type == IR::BoolType && target->type == IR::BoolType)
needsCall = false;
#if 0 // TODO: change masm to generate code
@@ -506,15 +514,18 @@ protected: // IRDecoder
}
#endif
+ IR::Temp *sourceTemp = source->asTemp();
if (needsCall) {
- addUses(sourceTemp, Use::CouldHaveRegister);
+ if (sourceTemp)
+ addUses(sourceTemp, Use::CouldHaveRegister);
addCall();
} else {
- addUses(sourceTemp, Use::MustHaveRegister);
+ if (sourceTemp)
+ addUses(sourceTemp, Use::MustHaveRegister);
}
}
- virtual void binop(AluOp oper, Expr *leftSource, Expr *rightSource, Temp *target)
+ virtual void binop(AluOp oper, Expr *leftSource, Expr *rightSource, Expr *target)
{
bool needsCall = true;
@@ -597,17 +608,22 @@ protected: // IRDecoder
}
protected:
- virtual void callBuiltin(IR::Call *c, IR::Temp *result)
+ virtual void callBuiltin(IR::Call *c, IR::Expr *result)
{
addDef(result);
- addUses(c->base->asTemp(), Use::CouldHaveRegister);
+ addUses(c->base, Use::CouldHaveRegister);
addUses(c->args, Use::CouldHaveRegister);
addCall();
}
private:
- void addDef(Temp *t, bool isPhiTarget = false)
+ void addDef(Expr *e, bool isPhiTarget = false)
{
+ if (!e)
+ return;
+ Temp *t = e->asTemp();
+ if (!t)
+ return;
if (!t || t->kind != Temp::VirtualRegister)
return;
Q_ASSERT(!_defs.contains(*t));
@@ -627,9 +643,14 @@ private:
_defs[*t] = Def(_currentStmt->id, canHaveReg, isPhiTarget);
}
- void addUses(Temp *t, Use::RegisterFlag flag)
+ void addUses(Expr *e, Use::RegisterFlag flag)
{
Q_ASSERT(_currentStmt->id > 0);
+ if (!e)
+ return;
+ Temp *t = e->asTemp();
+ if (!t)
+ return;
if (t && t->kind == Temp::VirtualRegister)
_uses[*t].append(Use(_currentStmt->id, flag));
}
@@ -637,7 +658,7 @@ private:
void addUses(ExprList *l, Use::RegisterFlag flag)
{
for (ExprList *it = l; it; it = it->next)
- addUses(it->expr->asTemp(), flag);
+ addUses(it->expr, flag);
}
void addCall()
@@ -645,6 +666,13 @@ private:
_calls.append(_currentStmt->id);
}
+ void addHint(Expr *hinted, Temp *hint1, Temp *hint2 = 0)
+ {
+ if (hinted)
+ if (Temp *hintedTemp = hinted->asTemp())
+ addHint(hintedTemp, hint1, hint2);
+ }
+
void addHint(Temp *hinted, Temp *hint1, Temp *hint2 = 0)
{
if (!hinted || hinted->kind != Temp::VirtualRegister)
@@ -986,7 +1014,7 @@ private:
{
Q_ASSERT(index >= 0);
Temp *t = _function->New<Temp>();
- t->init(kind, index, 0);
+ t->init(kind, index);
t->type = type;
return t;
}
@@ -1040,6 +1068,7 @@ protected:
}
}
+ virtual void visitArgLocal(ArgLocal *) {}
virtual void visitConst(Const *) {}
virtual void visitString(IR::String *) {}
virtual void visitRegExp(IR::RegExp *) {}
@@ -1140,7 +1169,7 @@ static inline LifeTimeInterval createFixedInterval(int rangeCount)
i.setReg(0);
Temp t;
- t.init(Temp::PhysicalRegister, 0, 0);
+ t.init(Temp::PhysicalRegister, 0);
t.type = IR::SInt32Type;
i.setTemp(t);
@@ -1153,7 +1182,7 @@ static inline LifeTimeInterval cloneFixedInterval(int reg, bool isFP, LifeTimeIn
lti.setFixedInterval(true);
Temp t;
- t.init(Temp::PhysicalRegister, reg, 0);
+ t.init(Temp::PhysicalRegister, reg);
t.type = isFP ? IR::DoubleType : IR::SInt32Type;
lti.setTemp(t);
diff --git a/src/qml/jit/qv4unop.cpp b/src/qml/jit/qv4unop.cpp
index 40f86f91b5..d92b5797cd 100644
--- a/src/qml/jit/qv4unop.cpp
+++ b/src/qml/jit/qv4unop.cpp
@@ -51,7 +51,7 @@ using namespace JIT;
#define setOp(operation) \
do { call = operation; name = stringIfy(operation); } while (0)
-void Unop::generate(IR::Temp *source, IR::Temp *target)
+void Unop::generate(IR::Expr *source, IR::Expr *target)
{
Runtime::UnaryOperation call = 0;
const char *name = 0;
@@ -77,16 +77,17 @@ void Unop::generate(IR::Temp *source, IR::Temp *target)
}
}
-void Unop::generateUMinus(IR::Temp *source, IR::Temp *target)
+void Unop::generateUMinus(IR::Expr *source, IR::Expr *target)
{
+ IR::Temp *targetTemp = target->asTemp();
if (source->type == IR::SInt32Type) {
Assembler::RegisterID tReg = Assembler::ScratchRegister;
- if (target->kind == IR::Temp::PhysicalRegister)
- tReg = (Assembler::RegisterID) target->index;
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister)
+ tReg = (Assembler::RegisterID) targetTemp->index;
Assembler::RegisterID sReg = as->toInt32Register(source, tReg);
as->move(sReg, tReg);
as->neg32(tReg);
- if (target->kind != IR::Temp::PhysicalRegister)
+ if (!targetTemp || targetTemp->kind != IR::Temp::PhysicalRegister)
as->storeInt32(tReg, target);
return;
}
@@ -94,24 +95,25 @@ void Unop::generateUMinus(IR::Temp *source, IR::Temp *target)
as->generateFunctionCallImp(target, "Runtime::uMinus", Runtime::uMinus, Assembler::PointerToValue(source));
}
-void Unop::generateNot(IR::Temp *source, IR::Temp *target)
+void Unop::generateNot(IR::Expr *source, IR::Expr *target)
{
+ IR::Temp *targetTemp = target->asTemp();
if (source->type == IR::BoolType) {
Assembler::RegisterID tReg = Assembler::ScratchRegister;
- if (target->kind == IR::Temp::PhysicalRegister)
- tReg = (Assembler::RegisterID) target->index;
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister)
+ tReg = (Assembler::RegisterID) targetTemp->index;
as->xor32(Assembler::TrustedImm32(0x1), as->toInt32Register(source, tReg), tReg);
- if (target->kind != IR::Temp::PhysicalRegister)
+ if (!targetTemp || targetTemp->kind != IR::Temp::PhysicalRegister)
as->storeBool(tReg, target);
return;
} else if (source->type == IR::SInt32Type) {
Assembler::RegisterID tReg = Assembler::ScratchRegister;
- if (target->kind == IR::Temp::PhysicalRegister)
- tReg = (Assembler::RegisterID) target->index;
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister)
+ tReg = (Assembler::RegisterID) targetTemp->index;
as->compare32(Assembler::Equal,
as->toInt32Register(source, Assembler::ScratchRegister), Assembler::TrustedImm32(0),
tReg);
- if (target->kind != IR::Temp::PhysicalRegister)
+ if (!targetTemp || targetTemp->kind != IR::Temp::PhysicalRegister)
as->storeBool(tReg, target);
return;
} else if (source->type == IR::DoubleType) {
@@ -122,14 +124,15 @@ void Unop::generateNot(IR::Temp *source, IR::Temp *target)
as->generateFunctionCallImp(target, "Runtime::uNot", Runtime::uNot, Assembler::PointerToValue(source));
}
-void Unop::generateCompl(IR::Temp *source, IR::Temp *target)
+void Unop::generateCompl(IR::Expr *source, IR::Expr *target)
{
+ IR::Temp *targetTemp = target->asTemp();
if (source->type == IR::SInt32Type) {
Assembler::RegisterID tReg = Assembler::ScratchRegister;
- if (target->kind == IR::Temp::PhysicalRegister)
- tReg = (Assembler::RegisterID) target->index;
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister)
+ tReg = (Assembler::RegisterID) targetTemp->index;
as->xor32(Assembler::TrustedImm32(0xffffffff), as->toInt32Register(source, tReg), tReg);
- if (target->kind != IR::Temp::PhysicalRegister)
+ if (!targetTemp || targetTemp->kind != IR::Temp::PhysicalRegister)
as->storeInt32(tReg, target);
return;
}
diff --git a/src/qml/jit/qv4unop_p.h b/src/qml/jit/qv4unop_p.h
index a8c62182ad..07fb6e5ad6 100644
--- a/src/qml/jit/qv4unop_p.h
+++ b/src/qml/jit/qv4unop_p.h
@@ -59,11 +59,11 @@ struct Unop {
, op(operation)
{}
- void generate(IR::Temp *source, IR::Temp *target);
+ void generate(IR::Expr *source, IR::Expr *target);
- void generateUMinus(IR::Temp *source, IR::Temp *target);
- void generateNot(IR::Temp *source, IR::Temp *target);
- void generateCompl(IR::Temp *source, IR::Temp *target);
+ void generateUMinus(IR::Expr *source, IR::Expr *target);
+ void generateNot(IR::Expr *source, IR::Expr *target);
+ void generateCompl(IR::Expr *source, IR::Expr *target);
Assembler *as;
IR::AluOp op;