diff options
author | Lars Knoll <lars.knoll@digia.com> | 2013-10-15 23:35:52 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-11-05 22:23:25 +0100 |
commit | 27a0d344000fedaf10b9f45c31a9cdd85df72a6b (patch) | |
tree | c57648ffea9dc5ea556fb0fe6e2487e620eb51a0 /src/qml/compiler | |
parent | 83947c254485f59f1660b172bddd190995353d81 (diff) |
Generate inline code for "foo == null/undefined"
Change-Id: I81f5708034ed50207afde697e377e8f265cbcd1c
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r-- | src/qml/compiler/qv4isel_masm.cpp | 88 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_masm_p.h | 3 |
2 files changed, 79 insertions, 12 deletions
diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp index cddaac08bd..58bf102c9d 100644 --- a/src/qml/compiler/qv4isel_masm.cpp +++ b/src/qml/compiler/qv4isel_masm.cpp @@ -1910,6 +1910,10 @@ void InstructionSelection::visitCJump(V4IR::CJump *s) visitCJumpStrict(b, s->iftrue, s->iffalse); return; } + if (b->op == V4IR::OpEqual || b->op == V4IR::OpNotEqual) { + visitCJumpEqual(b, s->iftrue, s->iffalse); + return; + } CmpOp op = 0; CmpOpContext opContext = 0; @@ -2339,6 +2343,8 @@ bool InstructionSelection::visitCJumpDouble(V4IR::AluOp op, V4IR::Expr *left, V4 void InstructionSelection::visitCJumpStrict(V4IR::Binop *binop, V4IR::BasicBlock *trueBlock, V4IR::BasicBlock *falseBlock) { + Q_ASSERT(binop->op == V4IR::OpStrictEqual || binop->op == V4IR::OpStrictNotEqual); + if (visitCJumpStrictNullUndefined(V4IR::NullType, binop, trueBlock, falseBlock)) return; if (visitCJumpStrictNullUndefined(V4IR::UndefinedType, binop, trueBlock, falseBlock)) @@ -2346,22 +2352,14 @@ void InstructionSelection::visitCJumpStrict(V4IR::Binop *binop, V4IR::BasicBlock if (visitCJumpStrictBool(binop, trueBlock, falseBlock)) return; - QV4::BinOp op; - const char *opName; - if (binop->op == V4IR::OpStrictEqual) { - op = __qmljs_se; - opName = "__qmljs_se"; - } else { - op = __qmljs_sne; - opName = "__qmljs_sne"; - } - V4IR::Expr *left = binop->left; V4IR::Expr *right = binop->right; - _as->generateFunctionCallImp(Assembler::ReturnValueRegister, opName, op, + _as->generateFunctionCallImp(Assembler::ReturnValueRegister, "__qmljs_cmp_se", __qmljs_cmp_se, Assembler::PointerToValue(left), Assembler::PointerToValue(right)); - _as->generateCJumpOnNonZero(Assembler::ReturnValueRegister, _block, trueBlock, falseBlock); + _as->generateCJumpOnCompare(binop->op == V4IR::OpStrictEqual ? Assembler::NotEqual : Assembler::Equal, + Assembler::ReturnValueRegister, Assembler::TrustedImm32(0), + _block, trueBlock, falseBlock); } // Only load the non-null temp. @@ -2463,6 +2461,72 @@ bool InstructionSelection::visitCJumpStrictBool(V4IR::Binop *binop, V4IR::BasicB return true; } +bool InstructionSelection::visitCJumpNullUndefined(V4IR::Type nullOrUndef, V4IR::Binop *binop, + V4IR::BasicBlock *trueBlock, + V4IR::BasicBlock *falseBlock) +{ + Q_ASSERT(nullOrUndef == V4IR::NullType || nullOrUndef == V4IR::UndefinedType); + + V4IR::Expr *varSrc = 0; + if (binop->left->type == V4IR::VarType && binop->right->type == nullOrUndef) + varSrc = binop->left; + else if (binop->left->type == nullOrUndef && binop->right->type == V4IR::VarType) + varSrc = binop->right; + if (!varSrc) + return false; + + if (varSrc->asTemp() && varSrc->asTemp()->kind == V4IR::Temp::PhysicalRegister) { + _as->jumpToBlock(_block, falseBlock); + return true; + } + + if (V4IR::Const *c = varSrc->asConst()) { + if (c->type == nullOrUndef) + _as->jumpToBlock(_block, trueBlock); + else + _as->jumpToBlock(_block, falseBlock); + return true; + } + + V4IR::Temp *t = varSrc->asTemp(); + Q_ASSERT(t); + + Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, t); + tagAddr.offset += 4; + const Assembler::RegisterID tagReg = Assembler::ScratchRegister; + _as->load32(tagAddr, tagReg); + + if (binop->op == V4IR::OpNotEqual) + qSwap(trueBlock, falseBlock); + Assembler::Jump isNull = _as->branch32(Assembler::Equal, tagReg, Assembler::TrustedImm32(int(QV4::Value::_Null_Type))); + Assembler::Jump isUndefined = _as->branch32(Assembler::Equal, tagReg, Assembler::TrustedImm32(int(QV4::Value::Undefined_Type))); + _as->addPatch(trueBlock, isNull); + _as->addPatch(trueBlock, isUndefined); + _as->jumpToBlock(_block, falseBlock); + + return true; +} + + +void InstructionSelection::visitCJumpEqual(V4IR::Binop *binop, V4IR::BasicBlock *trueBlock, + V4IR::BasicBlock *falseBlock) +{ + Q_ASSERT(binop->op == V4IR::OpEqual || binop->op == V4IR::OpNotEqual); + + if (visitCJumpNullUndefined(V4IR::NullType, binop, trueBlock, falseBlock)) + return; + + V4IR::Expr *left = binop->left; + V4IR::Expr *right = binop->right; + + _as->generateFunctionCallImp(Assembler::ReturnValueRegister, "__qmljs_cmp_eq", __qmljs_cmp_eq, + Assembler::PointerToValue(left), Assembler::PointerToValue(right)); + _as->generateCJumpOnCompare(binop->op == V4IR::OpEqual ? Assembler::NotEqual : Assembler::Equal, + Assembler::ReturnValueRegister, Assembler::TrustedImm32(0), + _block, trueBlock, falseBlock); +} + + bool InstructionSelection::int32Binop(V4IR::AluOp oper, V4IR::Expr *leftSource, V4IR::Expr *rightSource, V4IR::Temp *target) { diff --git a/src/qml/compiler/qv4isel_masm_p.h b/src/qml/compiler/qv4isel_masm_p.h index 72251f44d7..f84c981cd1 100644 --- a/src/qml/compiler/qv4isel_masm_p.h +++ b/src/qml/compiler/qv4isel_masm_p.h @@ -1545,6 +1545,9 @@ protected: bool visitCJumpStrictNullUndefined(V4IR::Type nullOrUndef, V4IR::Binop *binop, V4IR::BasicBlock *trueBlock, V4IR::BasicBlock *falseBlock); bool visitCJumpStrictBool(V4IR::Binop *binop, V4IR::BasicBlock *trueBlock, V4IR::BasicBlock *falseBlock); + bool visitCJumpNullUndefined(V4IR::Type nullOrUndef, V4IR::Binop *binop, + V4IR::BasicBlock *trueBlock, V4IR::BasicBlock *falseBlock); + void visitCJumpEqual(V4IR::Binop *binop, V4IR::BasicBlock *trueBlock, V4IR::BasicBlock *falseBlock); bool int32Binop(V4IR::AluOp oper, V4IR::Expr *leftSource, V4IR::Expr *rightSource, V4IR::Temp *target); |