aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMichael Brasser <michael.brasser@nokia.com>2012-03-14 11:35:13 +1000
committerQt by Nokia <qt-info@nokia.com>2012-03-15 13:18:17 +0100
commit20ffaaf2977255147ad8a45762d5efb6b5635829 (patch)
treefa163034fac34b6a7dcc731e63ac9d1ae3148e54 /src
parent49b451dae44d801524288d16d8f45a3ef583275e (diff)
Fix bug in v4 strict equality.
Change-Id: I184065e0b7c8c6536f2081b9bf03e98992a4c9fe Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/qml/qml/v4/qv4bindings.cpp45
-rw-r--r--src/qml/qml/v4/qv4compiler.cpp16
-rw-r--r--src/qml/qml/v4/qv4instruction.cpp15
-rw-r--r--src/qml/qml/v4/qv4instruction_p.h11
-rw-r--r--src/qml/qml/v4/qv4irbuilder.cpp28
-rw-r--r--src/qml/qml/v4/qv4program_p.h1
6 files changed, 103 insertions, 13 deletions
diff --git a/src/qml/qml/v4/qv4bindings.cpp b/src/qml/qml/v4/qv4bindings.cpp
index 89e831ca3f..5d367f2ae6 100644
--- a/src/qml/qml/v4/qv4bindings.cpp
+++ b/src/qml/qml/v4/qv4bindings.cpp
@@ -66,6 +66,7 @@ struct Register {
typedef QQmlRegisterType Type;
void setUndefined() { dataType = UndefinedType; }
+ void setNull() { dataType = NullType; }
void setNaN() { setqreal(qSNaN()); }
bool isUndefined() const { return dataType == UndefinedType; }
@@ -1239,6 +1240,10 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(MathPIReal, unaryop)
+ QML_V4_BEGIN_INSTR(LoadNull, null_value)
+ registers[instr->null_value.reg].setNull();
+ QML_V4_END_INSTR(LoadNull, null_value)
+
QML_V4_BEGIN_INSTR(LoadReal, real_value)
registers[instr->real_value.reg].setqreal(instr->real_value.value);
QML_V4_END_INSTR(LoadReal, real_value)
@@ -1521,6 +1526,46 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(StrictNotEqualString, binaryop)
+ QML_V4_BEGIN_INSTR(EqualObject, binaryop)
+ {
+ const Register &left = registers[instr->binaryop.left];
+ const Register &right = registers[instr->binaryop.right];
+ QObject *leftobj = (left.gettype() == NullType) ? 0 : left.getQObject();
+ QObject *rightobj = (right.gettype() == NullType) ? 0 : right.getQObject();
+ registers[instr->binaryop.output].setbool(leftobj == rightobj);
+ }
+ QML_V4_END_INSTR(EqualObject, binaryop)
+
+ QML_V4_BEGIN_INSTR(NotEqualObject, binaryop)
+ {
+ const Register &left = registers[instr->binaryop.left];
+ const Register &right = registers[instr->binaryop.right];
+ QObject *leftobj = (left.gettype() == NullType) ? 0 : left.getQObject();
+ QObject *rightobj = (right.gettype() == NullType) ? 0 : right.getQObject();
+ registers[instr->binaryop.output].setbool(leftobj != rightobj);
+ }
+ QML_V4_END_INSTR(NotEqualObject, binaryop)
+
+ QML_V4_BEGIN_INSTR(StrictEqualObject, binaryop)
+ {
+ const Register &left = registers[instr->binaryop.left];
+ const Register &right = registers[instr->binaryop.right];
+ QObject *leftobj = (left.gettype() == NullType) ? 0 : left.getQObject();
+ QObject *rightobj = (right.gettype() == NullType) ? 0 : right.getQObject();
+ registers[instr->binaryop.output].setbool(leftobj == rightobj);
+ }
+ QML_V4_END_INSTR(StrictEqualObject, binaryop)
+
+ QML_V4_BEGIN_INSTR(StrictNotEqualObject, binaryop)
+ {
+ const Register &left = registers[instr->binaryop.left];
+ const Register &right = registers[instr->binaryop.right];
+ QObject *leftobj = (left.gettype() == NullType) ? 0 : left.getQObject();
+ QObject *rightobj = (right.gettype() == NullType) ? 0 : right.getQObject();
+ registers[instr->binaryop.output].setbool(leftobj != rightobj);
+ }
+ QML_V4_END_INSTR(StrictNotEqualObject, binaryop)
+
QML_V4_BEGIN_INSTR(MathMaxReal, binaryop)
{
const Register &left = registers[instr->binaryop.left];
diff --git a/src/qml/qml/v4/qv4compiler.cpp b/src/qml/qml/v4/qv4compiler.cpp
index b22708d7db..09b0f3861b 100644
--- a/src/qml/qml/v4/qv4compiler.cpp
+++ b/src/qml/qml/v4/qv4compiler.cpp
@@ -234,6 +234,12 @@ void QV4CompilerPrivate::visitConst(IR::Const *e)
gen(i);
} break;
+ case IR::NullType: {
+ Instr::LoadNull i;
+ i.reg = currentReg;
+ gen(i);
+ } break;
+
default:
if (qmlVerboseCompiler())
qWarning() << Q_FUNC_INFO << "unexpected type";
@@ -682,21 +688,29 @@ quint8 QV4CompilerPrivate::instructionOpcode(IR::Binop *e)
return V4Instr::LeReal;
case IR::OpEqual:
+ if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType)
+ return V4Instr::EqualObject;
if (e->left->type == IR::StringType)
return V4Instr::EqualString;
return V4Instr::EqualReal;
case IR::OpNotEqual:
+ if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType)
+ return V4Instr::NotEqualObject;
if (e->left->type == IR::StringType)
return V4Instr::NotEqualString;
return V4Instr::NotEqualReal;
case IR::OpStrictEqual:
+ if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType)
+ return V4Instr::StrictEqualObject;
if (e->left->type == IR::StringType)
return V4Instr::StrictEqualString;
return V4Instr::StrictEqualReal;
case IR::OpStrictNotEqual:
+ if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType)
+ return V4Instr::StrictNotEqualObject;
if (e->left->type == IR::StringType)
return V4Instr::StrictNotEqualString;
return V4Instr::StrictNotEqualReal;
@@ -774,7 +788,7 @@ void QV4CompilerPrivate::visitBinop(IR::Binop *e)
case IR::OpNotEqual:
case IR::OpStrictEqual:
case IR::OpStrictNotEqual:
- if (e->left->type != IR::StringType) {
+ if (e->left->type >= IR::FirstNumberType) {
convertToReal(e->left, left);
convertToReal(e->right, right);
}
diff --git a/src/qml/qml/v4/qv4instruction.cpp b/src/qml/qml/v4/qv4instruction.cpp
index e26014765d..1ed8bd245e 100644
--- a/src/qml/qml/v4/qv4instruction.cpp
+++ b/src/qml/qml/v4/qv4instruction.cpp
@@ -213,6 +213,9 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::MathPIReal:
INSTR_DUMP << "\t" << "MathPIReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
+ case V4Instr::LoadNull:
+ INSTR_DUMP << "\t" << "LoadNull" << "\t\t" << "Constant(null) -> Output_Reg(" << i->null_value.reg << ")";
+ break;
case V4Instr::LoadReal:
INSTR_DUMP << "\t" << "LoadReal" << "\t\t" << "Constant(" << i->real_value.value << ") -> Output_Reg(" << i->real_value.reg << ")";
break;
@@ -315,6 +318,18 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::StrictNotEqualString:
INSTR_DUMP << "\t" << "StrictNotEqualString" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
+ case V4Instr::EqualObject:
+ INSTR_DUMP << "\t" << "EqualObject" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ break;
+ case V4Instr::NotEqualObject:
+ INSTR_DUMP << "\t" << "NotEqualObject" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ break;
+ case V4Instr::StrictEqualObject:
+ INSTR_DUMP << "\t" << "StrictEqualObject" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ break;
+ case V4Instr::StrictNotEqualObject:
+ INSTR_DUMP << "\t" << "StrictNotEqualObject" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ break;
case V4Instr::MathMaxReal:
INSTR_DUMP << "\t" << "MathMaxReal" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
diff --git a/src/qml/qml/v4/qv4instruction_p.h b/src/qml/qml/v4/qv4instruction_p.h
index d33051840d..d6c790e46f 100644
--- a/src/qml/qml/v4/qv4instruction_p.h
+++ b/src/qml/qml/v4/qv4instruction_p.h
@@ -106,6 +106,7 @@ QT_BEGIN_NAMESPACE
F(MathFloorReal, unaryop) \
F(MathCeilReal, unaryop) \
F(MathPIReal, unaryop) \
+ F(LoadNull, null_value) \
F(LoadReal, real_value) \
F(LoadInt, int_value) \
F(LoadBool, bool_value) \
@@ -140,6 +141,10 @@ QT_BEGIN_NAMESPACE
F(NotEqualString, binaryop) \
F(StrictEqualString, binaryop) \
F(StrictNotEqualString, binaryop) \
+ F(EqualObject, binaryop) \
+ F(NotEqualObject, binaryop) \
+ F(StrictEqualObject, binaryop) \
+ F(StrictNotEqualObject, binaryop) \
F(MathMaxReal, binaryop) \
F(MathMinReal, binaryop) \
F(NewString, construct) \
@@ -271,6 +276,11 @@ union V4Instr {
qint8 reg;
};
+ struct instr_null_value {
+ QML_V4_INSTR_HEADER
+ qint8 reg;
+ };
+
struct instr_real_value {
QML_V4_INSTR_HEADER
qint8 reg;
@@ -358,6 +368,7 @@ union V4Instr {
instr_fetch fetch;
instr_copy copy;
instr_construct construct;
+ instr_null_value null_value;
instr_real_value real_value;
instr_int_value int_value;
instr_bool_value bool_value;
diff --git a/src/qml/qml/v4/qv4irbuilder.cpp b/src/qml/qml/v4/qv4irbuilder.cpp
index 06178259f2..481b23eb4a 100644
--- a/src/qml/qml/v4/qv4irbuilder.cpp
+++ b/src/qml/qml/v4/qv4irbuilder.cpp
@@ -881,13 +881,15 @@ void QV4IRBuilder::binop(AST::BinaryExpression *ast, ExprResult left, ExprResult
implicitCvt(left, t);
implicitCvt(right, t);
}
+ } else if ((left.type() != IR::ObjectType && left.type() != IR::NullType) ||
+ (right.type() != IR::ObjectType && right.type() != IR::NullType))
+ return;
- if (_expr.hint == ExprResult::cx) {
- _expr.format = ExprResult::cx;
- _block->CJUMP(_block->BINOP(IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse);
- } else {
- _expr.code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
- }
+ if (_expr.hint == ExprResult::cx) {
+ _expr.format = ExprResult::cx;
+ _block->CJUMP(_block->BINOP(IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse);
+ } else {
+ _expr.code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
}
}
@@ -999,9 +1001,6 @@ bool QV4IRBuilder::visit(AST::BinaryExpression *ast)
implicitCvt(left, IR::RealType);
implicitCvt(right, IR::RealType);
binop(ast, left, right);
- } else if (left.type() == IR::BoolType || right.type() == IR::BoolType) {
- implicitCvt(left, IR::BoolType);
- implicitCvt(right, IR::BoolType);
} else if (left.isValid() && right.isValid()) {
binop(ast, left, right);
}
@@ -1013,16 +1012,21 @@ bool QV4IRBuilder::visit(AST::BinaryExpression *ast)
ExprResult right = expression(ast->right);
if (left.type() == right.type()) {
binop(ast, left, right);
- } else if (left.type() >= IR::BoolType && right.type() >= IR::BoolType) {
+ } else if (left.type() > IR::BoolType && right.type() > IR::BoolType) {
// left and right have numeric type (int or real)
binop(ast, left, right);
+ } else if ((left.type() == IR::ObjectType && right.type() == IR::NullType) ||
+ (right.type() == IR::ObjectType && left.type() == IR::NullType)) {
+ // comparing a qobject with null
+ binop(ast, left, right);
} else if (left.isValid() && right.isValid()) {
+ // left and right have different types
const bool isEq = ast->op == QSOperator::StrictEqual;
if (_expr.hint == ExprResult::cx) {
_expr.format = ExprResult::cx;
- _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse);
+ _block->JUMP(isEq ? _expr.iffalse : _expr.iftrue);
} else {
- _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0);
+ _expr.code = _block->CONST(IR::BoolType, isEq ? 0 : 1);
}
}
} break;
diff --git a/src/qml/qml/v4/qv4program_p.h b/src/qml/qml/v4/qv4program_p.h
index d23cc6192f..60e7403786 100644
--- a/src/qml/qml/v4/qv4program_p.h
+++ b/src/qml/qml/v4/qv4program_p.h
@@ -85,6 +85,7 @@ struct QV4Program {
enum QQmlRegisterType {
UndefinedType,
+ NullType,
QObjectStarType,
QRealType,
IntType,