⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jitarithmetic.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    return check.present;}#endifvoid JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes types){    Structure* numberStructure = m_globalData->numberStructure.get();    JmpSrc wasJSNumberCell1;    JmpSrc wasJSNumberCell2;    emitGetVirtualRegisters(src1, X86::eax, src2, X86::edx);    if (types.second().isReusable() && isSSE2Present()) {        ASSERT(types.second().mightBeNumber());        // Check op2 is a number        __ testl_i32r(JSImmediate::TagTypeNumber, X86::edx);        JmpSrc op2imm = __ jne();        if (!types.second().definitelyIsNumber()) {            emitJumpSlowCaseIfNotJSCell(X86::edx, src2);            __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::edx);            addSlowCase(__ jne());        }        // (1) In this case src2 is a reusable number cell.        //     Slow case if src1 is not a number type.        __ testl_i32r(JSImmediate::TagTypeNumber, X86::eax);        JmpSrc op1imm = __ jne();        if (!types.first().definitelyIsNumber()) {            emitJumpSlowCaseIfNotJSCell(X86::eax, src1);            __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax);            addSlowCase(__ jne());        }        // (1a) if we get here, src1 is also a number cell        __ movsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::eax, X86::xmm0);        JmpSrc loadedDouble = __ jmp();        // (1b) if we get here, src1 is an immediate        __ linkJump(op1imm, __ label());        emitFastArithImmToInt(X86::eax);        __ cvtsi2sd_rr(X86::eax, X86::xmm0);        // (1c)         __ linkJump(loadedDouble, __ label());        if (opcodeID == op_add)            __ addsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0);        else if (opcodeID == op_sub)            __ subsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0);        else {            ASSERT(opcodeID == op_mul);            __ mulsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0);        }        // Store the result to the JSNumberCell and jump.        __ movsd_rm(X86::xmm0, FIELD_OFFSET(JSNumberCell, m_value), X86::edx);        __ movl_rr(X86::edx, X86::eax);        emitPutVirtualRegister(dst);        wasJSNumberCell2 = __ jmp();        // (2) This handles cases where src2 is an immediate number.        //     Two slow cases - either src1 isn't an immediate, or the subtract overflows.        __ linkJump(op2imm, __ label());        emitJumpSlowCaseIfNotImmediateInteger(X86::eax);    } else if (types.first().isReusable() && isSSE2Present()) {        ASSERT(types.first().mightBeNumber());        // Check op1 is a number        __ testl_i32r(JSImmediate::TagTypeNumber, X86::eax);        JmpSrc op1imm = __ jne();        if (!types.first().definitelyIsNumber()) {            emitJumpSlowCaseIfNotJSCell(X86::eax, src1);            __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax);            addSlowCase(__ jne());        }        // (1) In this case src1 is a reusable number cell.        //     Slow case if src2 is not a number type.        __ testl_i32r(JSImmediate::TagTypeNumber, X86::edx);        JmpSrc op2imm = __ jne();        if (!types.second().definitelyIsNumber()) {            emitJumpSlowCaseIfNotJSCell(X86::edx, src2);            __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::edx);            addSlowCase(__ jne());        }        // (1a) if we get here, src2 is also a number cell        __ movsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm1);        JmpSrc loadedDouble = __ jmp();        // (1b) if we get here, src2 is an immediate        __ linkJump(op2imm, __ label());        emitFastArithImmToInt(X86::edx);        __ cvtsi2sd_rr(X86::edx, X86::xmm1);        // (1c)         __ linkJump(loadedDouble, __ label());        __ movsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::eax, X86::xmm0);        if (opcodeID == op_add)            __ addsd_rr(X86::xmm1, X86::xmm0);        else if (opcodeID == op_sub)            __ subsd_rr(X86::xmm1, X86::xmm0);        else {            ASSERT(opcodeID == op_mul);            __ mulsd_rr(X86::xmm1, X86::xmm0);        }        __ movsd_rm(X86::xmm0, FIELD_OFFSET(JSNumberCell, m_value), X86::eax);        emitPutVirtualRegister(dst);        // Store the result to the JSNumberCell and jump.        __ movsd_rm(X86::xmm0, FIELD_OFFSET(JSNumberCell, m_value), X86::eax);        emitPutVirtualRegister(dst);        wasJSNumberCell1 = __ jmp();        // (2) This handles cases where src1 is an immediate number.        //     Two slow cases - either src2 isn't an immediate, or the subtract overflows.        __ linkJump(op1imm, __ label());        emitJumpSlowCaseIfNotImmediateInteger(X86::edx);    } else        emitJumpSlowCaseIfNotImmediateIntegers(X86::eax, X86::edx, X86::ecx);    if (opcodeID == op_add) {        emitFastArithDeTagImmediate(X86::eax);        __ addl_rr(X86::edx, X86::eax);        addSlowCase(__ jo());    } else  if (opcodeID == op_sub) {        __ subl_rr(X86::edx, X86::eax);        addSlowCase(__ jo());        signExtend32ToPtr(X86::eax, X86::eax);        emitFastArithReTagImmediate(X86::eax, X86::eax);    } else {        ASSERT(opcodeID == op_mul);        // convert eax & edx from JSImmediates to ints, and check if either are zero        emitFastArithImmToInt(X86::edx);        Jump op1Zero = emitFastArithDeTagImmediateJumpIfZero(X86::eax);        __ testl_rr(X86::edx, X86::edx);        JmpSrc op2NonZero = __ jne();        op1Zero.link(this);        // if either input is zero, add the two together, and check if the result is < 0.        // If it is, we have a problem (N < 0), (N * 0) == -0, not representatble as a JSImmediate.         __ movl_rr(X86::eax, X86::ecx);        __ addl_rr(X86::edx, X86::ecx);        addSlowCase(__ js());        // Skip the above check if neither input is zero        __ linkJump(op2NonZero, __ label());        __ imull_rr(X86::edx, X86::eax);        addSlowCase(__ jo());        signExtend32ToPtr(X86::eax, X86::eax);        emitFastArithReTagImmediate(X86::eax, X86::eax);    }    emitPutVirtualRegister(dst);    if (types.second().isReusable() && isSSE2Present()) {        __ linkJump(wasJSNumberCell2, __ label());    }    else if (types.first().isReusable() && isSSE2Present()) {        __ linkJump(wasJSNumberCell1, __ label());    }}void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned dst, unsigned src1, unsigned src2, OperandTypes types){    linkSlowCase(iter);    if (types.second().isReusable() && isSSE2Present()) {        if (!types.first().definitelyIsNumber()) {            linkSlowCaseIfNotJSCell(iter, src1);            linkSlowCase(iter);        }        if (!types.second().definitelyIsNumber()) {            linkSlowCaseIfNotJSCell(iter, src2);            linkSlowCase(iter);        }    } else if (types.first().isReusable() && isSSE2Present()) {        if (!types.first().definitelyIsNumber()) {            linkSlowCaseIfNotJSCell(iter, src1);            linkSlowCase(iter);        }        if (!types.second().definitelyIsNumber()) {            linkSlowCaseIfNotJSCell(iter, src2);            linkSlowCase(iter);        }    }    linkSlowCase(iter);    // additional entry point to handle -0 cases.    if (opcodeID == op_mul)        linkSlowCase(iter);    emitPutJITStubArgFromVirtualRegister(src1, 1, X86::ecx);    emitPutJITStubArgFromVirtualRegister(src2, 2, X86::ecx);    if (opcodeID == op_add)        emitCTICall(JITStubs::cti_op_add);    else if (opcodeID == op_sub)        emitCTICall(JITStubs::cti_op_sub);    else {        ASSERT(opcodeID == op_mul);        emitCTICall(JITStubs::cti_op_mul);    }    emitPutVirtualRegister(dst);}void JIT::compileFastArith_op_add(Instruction* currentInstruction){    unsigned result = currentInstruction[1].u.operand;    unsigned op1 = currentInstruction[2].u.operand;    unsigned op2 = currentInstruction[3].u.operand;    if (isOperandConstantImmediateInt(op1)) {        emitGetVirtualRegister(op2, X86::eax);        emitJumpSlowCaseIfNotImmediateInteger(X86::eax);        addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), X86::eax));        signExtend32ToPtr(X86::eax, X86::eax);        emitPutVirtualRegister(result);    } else if (isOperandConstantImmediateInt(op2)) {        emitGetVirtualRegister(op1, X86::eax);        emitJumpSlowCaseIfNotImmediateInteger(X86::eax);        addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), X86::eax));        signExtend32ToPtr(X86::eax, X86::eax);        emitPutVirtualRegister(result);    } else {        OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);        if (types.first().mightBeNumber() && types.second().mightBeNumber())            compileBinaryArithOp(op_add, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));        else {            emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);            emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);            emitCTICall(JITStubs::cti_op_add);            emitPutVirtualRegister(result);        }    }}void JIT::compileFastArithSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter){    unsigned result = currentInstruction[1].u.operand;    unsigned op1 = currentInstruction[2].u.operand;    unsigned op2 = currentInstruction[3].u.operand;    if (isOperandConstantImmediateInt(op1)) {        Jump notImm = getSlowCase(iter);        linkSlowCase(iter);        sub32(Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), X86::eax);        notImm.link(this);        emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);        emitPutJITStubArg(X86::eax, 2);        emitCTICall(JITStubs::cti_op_add);        emitPutVirtualRegister(result);    } else if (isOperandConstantImmediateInt(op2)) {        Jump notImm = getSlowCase(iter);        linkSlowCase(iter);        sub32(Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), X86::eax);        notImm.link(this);        emitPutJITStubArg(X86::eax, 1);        emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);        emitCTICall(JITStubs::cti_op_add);        emitPutVirtualRegister(result);    } else {        OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);        ASSERT(types.first().mightBeNumber() && types.second().mightBeNumber());        compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, types);    }}void JIT::compileFastArith_op_mul(Instruction* currentInstruction){    unsigned result = currentInstruction[1].u.operand;    unsigned op1 = currentInstruction[2].u.operand;    unsigned op2 = currentInstruction[3].u.operand;    // For now, only plant a fast int case if the constant operand is greater than zero.    int32_t value;    if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) {        emitGetVirtualRegister(op2, X86::eax);        emitJumpSlowCaseIfNotImmediateInteger(X86::eax);        emitFastArithDeTagImmediate(X86::eax);        addSlowCase(branchMul32(Overflow, Imm32(value), X86::eax, X86::eax));        signExtend32ToPtr(X86::eax, X86::eax);        emitFastArithReTagImmediate(X86::eax, X86::eax);        emitPutVirtualRegister(result);    } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) {        emitGetVirtualRegister(op1, X86::eax);        emitJumpSlowCaseIfNotImmediateInteger(X86::eax);        emitFastArithDeTagImmediate(X86::eax);        addSlowCase(branchMul32(Overflow, Imm32(value), X86::eax, X86::eax));        signExtend32ToPtr(X86::eax, X86::eax);        emitFastArithReTagImmediate(X86::eax, X86::eax);        emitPutVirtualRegister(result);    } else        compileBinaryArithOp(op_mul, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));}void JIT::compileFastArithSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter){    unsigned result = currentInstruction[1].u.operand;    unsigned op1 = currentInstruction[2].u.operand;    unsigned op2 = currentInstruction[3].u.operand;    if ((isOperandConstantImmediateInt(op1) && (getConstantOperandImmediateInt(op1) > 0))        || (isOperandConstantImmediateInt(op2) && (getConstantOperandImmediateInt(op2) > 0))) {        linkSlowCase(iter);        linkSlowCase(iter);        // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.        emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);        emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);        emitCTICall(JITStubs::cti_op_mul);        emitPutVirtualRegister(result);    } else        compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));}void JIT::compileFastArith_op_sub(Instruction* currentInstruction){    compileBinaryArithOp(op_sub, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand));}void JIT::compileFastArithSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter){    compileBinaryArithOpSlowCase(op_sub, iter, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand));}#endif} // namespace JSC#endif // ENABLE(JIT)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -