📄 jitarithmetic.cpp
字号:
addSlowCase(branchSub32(Zero, Imm32(1), regT0)); emitFastArithIntToImmNoCheck(regT0, regT0);#else addSlowCase(branchSub32(Zero, Imm32(1 << JSImmediate::IntegerPayloadShift), regT0)); signExtend32ToPtr(regT0, regT0);#endif emitPutVirtualRegister(srcDst);}void JIT::compileFastArithSlow_op_pre_dec(unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter){ Jump notImm = getSlowCase(iter); linkSlowCase(iter); emitGetVirtualRegister(srcDst, regT0); notImm.link(this); emitPutJITStubArg(regT0, 1); emitCTICall(JITStubs::cti_op_pre_dec); emitPutVirtualRegister(srcDst);}#if !ENABLE(JIT_OPTIMIZE_ARITHMETIC)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; emitPutJITStubArgFromVirtualRegister(op1, 1, regT2); emitPutJITStubArgFromVirtualRegister(op2, 2, regT2); emitCTICall(JITStubs::cti_op_add); emitPutVirtualRegister(result);}void JIT::compileFastArithSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&){ ASSERT_NOT_REACHED();}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; emitPutJITStubArgFromVirtualRegister(op1, 1, regT2); emitPutJITStubArgFromVirtualRegister(op2, 2, regT2); emitCTICall(JITStubs::cti_op_mul); emitPutVirtualRegister(result);}void JIT::compileFastArithSlow_op_mul(Instruction*, Vector<SlowCaseEntry>::iterator&){ ASSERT_NOT_REACHED();}void JIT::compileFastArith_op_sub(Instruction* currentInstruction){ unsigned result = currentInstruction[1].u.operand; unsigned op1 = currentInstruction[2].u.operand; unsigned op2 = currentInstruction[3].u.operand; emitPutJITStubArgFromVirtualRegister(op1, 1, regT2); emitPutJITStubArgFromVirtualRegister(op2, 2, regT2); emitCTICall(JITStubs::cti_op_sub); emitPutVirtualRegister(result);}void JIT::compileFastArithSlow_op_sub(Instruction*, Vector<SlowCaseEntry>::iterator&){ ASSERT_NOT_REACHED();}#elif USE(ALTERNATE_JSIMMEDIATE) // *AND* ENABLE(JIT_OPTIMIZE_ARITHMETIC)void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned, unsigned op1, unsigned op2, OperandTypes){ emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx); emitJumpSlowCaseIfNotImmediateInteger(X86::eax); emitJumpSlowCaseIfNotImmediateInteger(X86::edx); if (opcodeID == op_add) addSlowCase(branchAdd32(Overflow, X86::edx, X86::eax)); else if (opcodeID == op_sub) addSlowCase(branchSub32(Overflow, X86::edx, X86::eax)); else { ASSERT(opcodeID == op_mul); addSlowCase(branchMul32(Overflow, X86::edx, X86::eax)); addSlowCase(branchTest32(Zero, X86::eax)); } emitFastArithIntToImmNoCheck(X86::eax, X86::eax);}void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned, unsigned op1, unsigned, OperandTypes types){ // We assume that subtracting TagTypeNumber is equivalent to adding DoubleEncodeOffset. COMPILE_ASSERT(((JSImmediate::TagTypeNumber + JSImmediate::DoubleEncodeOffset) == 0), TagTypeNumber_PLUS_DoubleEncodeOffset_EQUALS_0); Jump notImm1 = getSlowCase(iter); Jump notImm2 = getSlowCase(iter); linkSlowCase(iter); // Integer overflow case - we could handle this in JIT code, but this is likely rare. if (opcodeID == op_mul) // op_mul has an extra slow case to handle 0 * negative number. linkSlowCase(iter); emitGetVirtualRegister(op1, X86::eax); Label stubFunctionCall(this); emitPutJITStubArg(X86::eax, 1); emitPutJITStubArg(X86::edx, 2); 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); } Jump end = jump(); // if we get here, eax is not an int32, edx not yet checked. notImm1.link(this); if (!types.first().definitelyIsNumber()) emitJumpIfNotImmediateNumber(X86::eax).linkTo(stubFunctionCall, this); if (!types.second().definitelyIsNumber()) emitJumpIfNotImmediateNumber(X86::edx).linkTo(stubFunctionCall, this); addPtr(tagTypeNumberRegister, X86::eax); m_assembler.movq_rr(X86::eax, X86::xmm1); Jump op2isDouble = emitJumpIfNotImmediateInteger(X86::edx); m_assembler.cvtsi2sd_rr(X86::edx, X86::xmm2); Jump op2wasInteger = jump(); // if we get here, eax IS an int32, edx is not. notImm2.link(this); if (!types.second().definitelyIsNumber()) emitJumpIfNotImmediateNumber(X86::edx).linkTo(stubFunctionCall, this); m_assembler.cvtsi2sd_rr(X86::eax, X86::xmm1); op2isDouble.link(this); addPtr(tagTypeNumberRegister, X86::edx); m_assembler.movq_rr(X86::edx, X86::xmm2); op2wasInteger.link(this); if (opcodeID == op_add) m_assembler.addsd_rr(X86::xmm2, X86::xmm1); else if (opcodeID == op_sub) m_assembler.subsd_rr(X86::xmm2, X86::xmm1); else { ASSERT(opcodeID == op_mul); m_assembler.mulsd_rr(X86::xmm2, X86::xmm1); } m_assembler.movq_rr(X86::xmm1, X86::eax); subPtr(tagTypeNumberRegister, X86::eax); end.link(this);}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; OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) { emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx); emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx); emitCTICall(JITStubs::cti_op_add); emitPutVirtualRegister(result); return; } if (isOperandConstantImmediateInt(op1)) { emitGetVirtualRegister(op2, X86::eax); emitJumpSlowCaseIfNotImmediateInteger(X86::eax); addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op1)), X86::eax)); emitFastArithIntToImmNoCheck(X86::eax, X86::eax); } else if (isOperandConstantImmediateInt(op2)) { emitGetVirtualRegister(op1, X86::eax); emitJumpSlowCaseIfNotImmediateInteger(X86::eax); addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op2)), X86::eax)); emitFastArithIntToImmNoCheck(X86::eax, X86::eax); } else compileBinaryArithOp(op_add, result, op1, op2, types); 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; OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); if (isOperandConstantImmediateInt(op1)) { linkSlowCase(iter); linkSlowCase(iter); emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx); emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx); emitCTICall(JITStubs::cti_op_add); } else if (isOperandConstantImmediateInt(op2)) { linkSlowCase(iter); linkSlowCase(iter); emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx); emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx); emitCTICall(JITStubs::cti_op_add); } else compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, types); emitPutVirtualRegister(result);}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; OperandTypes types = OperandTypes::fromInt(currentInstruction[4].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); addSlowCase(branchMul32(Overflow, Imm32(value), X86::eax, X86::eax)); emitFastArithReTagImmediate(X86::eax, X86::eax); } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) { emitGetVirtualRegister(op1, X86::eax); emitJumpSlowCaseIfNotImmediateInteger(X86::eax); addSlowCase(branchMul32(Overflow, Imm32(value), X86::eax, X86::eax)); emitFastArithReTagImmediate(X86::eax, X86::eax); } else compileBinaryArithOp(op_mul, result, op1, op2, types); emitPutVirtualRegister(result);}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; OperandTypes types = OperandTypes::fromInt(currentInstruction[4].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); } else compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, types); emitPutVirtualRegister(result);}void JIT::compileFastArith_op_sub(Instruction* currentInstruction){ unsigned result = currentInstruction[1].u.operand; unsigned op1 = currentInstruction[2].u.operand; unsigned op2 = currentInstruction[3].u.operand; OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); compileBinaryArithOp(op_sub, result, op1, op2, types); emitPutVirtualRegister(result);}void JIT::compileFastArithSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter){ unsigned result = currentInstruction[1].u.operand; unsigned op1 = currentInstruction[2].u.operand; unsigned op2 = currentInstruction[3].u.operand; OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); compileBinaryArithOpSlowCase(op_sub, iter, result, op1, op2, types); emitPutVirtualRegister(result);}#elsetypedef X86Assembler::JmpSrc JmpSrc;typedef X86Assembler::JmpDst JmpDst;typedef X86Assembler::XMMRegisterID XMMRegisterID;#if PLATFORM(MAC)static inline bool isSSE2Present(){ return true; // All X86 Macs are guaranteed to support at least SSE2}#elsestatic bool isSSE2Present(){ static const int SSE2FeatureBit = 1 << 26; struct SSE2Check { SSE2Check() { int flags;#if COMPILER(MSVC) _asm { mov eax, 1 // cpuid function 1 gives us the standard feature set cpuid; mov flags, edx; }#elif COMPILER(GCC) asm ( "movl $0x1, %%eax;" "pushl %%ebx;" "cpuid;" "popl %%ebx;" "movl %%edx, %0;" : "=g" (flags) : : "%eax", "%ecx", "%edx" );#else flags = 0;#endif present = (flags & SSE2FeatureBit) != 0; } bool present; }; static SSE2Check check;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -