diff options
-rw-r--r-- | src/qml/compiler/qqmltypecompiler_p.h | 1 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 63 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_moth.cpp | 182 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_moth_p.h | 86 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_p.cpp | 108 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_p.h | 84 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_util_p.h | 1 | ||||
-rw-r--r-- | src/qml/compiler/qv4jsir.cpp | 45 | ||||
-rw-r--r-- | src/qml/compiler/qv4jsir_p.h | 78 | ||||
-rw-r--r-- | src/qml/compiler/qv4ssa.cpp | 155 | ||||
-rw-r--r-- | src/qml/jit/qv4assembler.cpp | 49 | ||||
-rw-r--r-- | src/qml/jit/qv4assembler_p.h | 208 | ||||
-rw-r--r-- | src/qml/jit/qv4binop.cpp | 50 | ||||
-rw-r--r-- | src/qml/jit/qv4binop_p.h | 8 | ||||
-rw-r--r-- | src/qml/jit/qv4isel_masm.cpp | 314 | ||||
-rw-r--r-- | src/qml/jit/qv4isel_masm_p.h | 137 | ||||
-rw-r--r-- | src/qml/jit/qv4regalloc.cpp | 149 | ||||
-rw-r--r-- | src/qml/jit/qv4unop.cpp | 35 | ||||
-rw-r--r-- | src/qml/jit/qv4unop_p.h | 8 |
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; |