From: Simon Hausmann Date: Sun, 2 Dec 2012 00:04:34 +0000 (+0100) Subject: [masm] First implementation of inline addition / subtraction X-Git-Tag: upstream/5.2.1~669^2~659^2~770 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4c2f11c67dadb684a602ecad397763804b62adf9;p=platform%2Fupstream%2Fqtdeclarative.git [masm] First implementation of inline addition / subtraction Change-Id: I4e54ae0feded8d99737245c870e0dfbb9b80247e Reviewed-by: Lars Knoll --- diff --git a/qv4isel_masm.cpp b/qv4isel_masm.cpp index 5f95442..37ad3fe 100644 --- a/qv4isel_masm.cpp +++ b/qv4isel_masm.cpp @@ -484,6 +484,8 @@ void InstructionSelection::visitMove(IR::Move *s) (b->right->asTemp() || b->right->asConst())) { Value (*op)(const Value, const Value, ExecutionContext *) = 0; const char* opName = 0; + MemBinOpWithOverFlow inlineMemBinOp = 0; + ImmBinOpWithOverFlow inlineImmBinOp = 0; switch ((IR::AluOp) b->op) { case IR::OpInvalid: @@ -498,8 +500,18 @@ void InstructionSelection::visitMove(IR::Move *s) case IR::OpBitAnd: setOp(op, opName, __qmljs_bit_and); break; case IR::OpBitOr: setOp(op, opName, __qmljs_bit_or); break; case IR::OpBitXor: setOp(op, opName, __qmljs_bit_xor); break; - case IR::OpAdd: setOp(op, opName, __qmljs_add); break; - case IR::OpSub: setOp(op, opName, __qmljs_sub); break; + case IR::OpAdd: { + setOp(op, opName, __qmljs_add); + inlineMemBinOp = &JSC::MacroAssembler::branchAdd32; + inlineImmBinOp = &JSC::MacroAssembler::branchAdd32; + break; + } + case IR::OpSub: { + setOp(op, opName, __qmljs_sub); + inlineMemBinOp = &JSC::MacroAssembler::branchSub32; + inlineImmBinOp = &JSC::MacroAssembler::branchSub32; + break; + } case IR::OpMul: setOp(op, opName, __qmljs_mul); break; case IR::OpDiv: setOp(op, opName, __qmljs_div); break; case IR::OpMod: setOp(op, opName, __qmljs_mod); break; @@ -524,7 +536,11 @@ void InstructionSelection::visitMove(IR::Move *s) } if (op) { - generateFunctionCallImp(t, opName, op, b->left, b->right, ContextRegister); + if (inlineMemBinOp && inlineImmBinOp + && generateArithmeticIntegerInlineBinOp(t, b->left, b->right, inlineMemBinOp, inlineImmBinOp, op, opName)) + return; + else + generateFunctionCallImp(t, opName, op, b->left, b->right, ContextRegister); } return; } @@ -803,3 +819,75 @@ void InstructionSelection::copyValue(Result result, Source source) storeDouble(FPGpr0, result); #endif } + +bool InstructionSelection::generateArithmeticIntegerInlineBinOp(IR::Temp* target, IR::Expr* left, IR::Expr* right, + MemBinOpWithOverFlow memOp, ImmBinOpWithOverFlow immOp, FallbackOp fallbackOp, const char* fallbackOpName) +{ + VM::Value leftConst; + if (left->asConst()) { + leftConst = convertToValue(left->asConst()); + if (!leftConst.tryIntegerConversion()) + return false; + } + VM::Value rightConst; + if (right->asConst()) { + rightConst = convertToValue(right->asConst()); + if (!rightConst.tryIntegerConversion()) + return false; + } + + Jump leftTypeCheck; + if (left->asTemp()) { + Address typeAddress = loadTempAddress(ScratchRegister, left->asTemp()); + typeAddress.offset += offsetof(VM::Value, tag); + leftTypeCheck = branch32(NotEqual, typeAddress, TrustedImm32(VM::Value::_Integer_Type)); + } + + Jump rightTypeCheck; + if (right->asTemp()) { + Address typeAddress = loadTempAddress(ScratchRegister, right->asTemp()); + typeAddress.offset += offsetof(VM::Value, tag); + rightTypeCheck = branch32(NotEqual, typeAddress, TrustedImm32(VM::Value::_Integer_Type)); + } + + if (left->asTemp()) { + Address leftValue = loadTempAddress(ScratchRegister, left->asTemp()); + leftValue.offset += offsetof(VM::Value, int_32); + load32(leftValue, IntegerOpRegister); + } else { // left->asConst() + move(TrustedImm32(leftConst.integerValue()), IntegerOpRegister); + } + + Jump overflowCheck; + + if (right->asTemp()) { + Address rightValue = loadTempAddress(ScratchRegister, right->asTemp()); + rightValue.offset += offsetof(VM::Value, int_32); + + overflowCheck = (this->*memOp)(Overflow, rightValue, IntegerOpRegister); + } else { // right->asConst() + VM::Value value = convertToValue(right->asConst()); + overflowCheck = (this->*immOp)(Overflow, TrustedImm32(value.integerValue()), IntegerOpRegister); + } + + Address resultAddr = loadTempAddress(ScratchRegister, target); + Address resultValueAddr = resultAddr; + resultValueAddr.offset += offsetof(VM::Value, int_32); + store32(IntegerOpRegister, resultValueAddr); + + Address resultTypeAddr = resultAddr; + resultTypeAddr.offset += offsetof(VM::Value, tag); + store32(TrustedImm32(VM::Value::_Integer_Type), resultTypeAddr); + + Jump finishBinOp = jump(); + + if (leftTypeCheck.isSet()) + leftTypeCheck.link(this); + if (rightTypeCheck.isSet()) + rightTypeCheck.link(this); + overflowCheck.link(this); + generateFunctionCallImp(target, fallbackOpName, fallbackOp, left, right, ContextRegister); + + finishBinOp.link(this); + return true; +} diff --git a/qv4isel_masm_p.h b/qv4isel_masm_p.h index 1b3cee1..55e75d3 100644 --- a/qv4isel_masm_p.h +++ b/qv4isel_masm_p.h @@ -77,6 +77,7 @@ protected: static const RegisterID ScratchRegister = JSC::X86Registers::ecx; static const RegisterID CalleeSavedFirstRegister = ScratchRegister; static const RegisterID CalleeSavedLastRegister = ScratchRegister; + static const RegisterID IntegerOpRegister = JSC::X86Registers::eax; static const FPRegisterID FPGpr0 = JSC::X86Registers::xmm0; static const int RegisterSize = 4; @@ -97,6 +98,7 @@ protected: static const RegisterID ContextRegister = JSC::X86Registers::r14; static const RegisterID ReturnValueRegister = JSC::X86Registers::eax; static const RegisterID ScratchRegister = JSC::X86Registers::r10; + static const RegisterID IntegerOpRegister = JSC::X86Registers::eax; static const FPRegisterID FPGpr0 = JSC::X86Registers::xmm0; static const int RegisterSize = 8; @@ -126,6 +128,7 @@ protected: static const RegisterID ScratchRegister = JSC::ARMRegisters::r6; static const RegisterID CalleeSavedFirstRegister = JSC::ARMRegisters::r4; static const RegisterID CalleeSavedLastRegister = JSC::ARMRegisters::r11; + static const RegisterID IntegerOpRegister = JSC::X86Registers::r0; static const FPRegisterID FPGpr0 = JSC::ARMRegisters::d0; static const int RegisterSize = 4; @@ -608,6 +611,13 @@ private: #endif } + typedef VM::Value (*FallbackOp)(const VM::Value, const VM::Value, VM::ExecutionContext*); + + typedef Jump (JSC::MacroAssembler::*MemBinOpWithOverFlow)(ResultCondition, Address, RegisterID); + typedef Jump (JSC::MacroAssembler::*ImmBinOpWithOverFlow)(ResultCondition, TrustedImm32, RegisterID); + bool generateArithmeticIntegerInlineBinOp(IR::Temp* target, IR::Expr* left, IR::Expr* right, + MemBinOpWithOverFlow memOp, ImmBinOpWithOverFlow immOp, FallbackOp fallback, const char* fallbackOpName); + VM::ExecutionEngine *_engine; IR::Function *_function; IR::BasicBlock *_block;