JITMathICInlineResult JITNegGenerator::generateInline(CCallHelpers& jit, MathICGenerationState& state, const ArithProfile* arithProfile) { ASSERT(m_scratchGPR != InvalidGPRReg); ASSERT(m_scratchGPR != m_src.payloadGPR()); ASSERT(m_scratchGPR != m_result.payloadGPR()); #if USE(JSVALUE32_64) ASSERT(m_scratchGPR != m_src.tagGPR()); ASSERT(m_scratchGPR != m_result.tagGPR()); #endif // We default to speculating int32. ObservedType observedTypes = ObservedType().withInt32(); if (arithProfile) observedTypes = arithProfile->lhsObservedType(); ASSERT_WITH_MESSAGE(!observedTypes.isEmpty(), "We should not attempt to generate anything if we do not have a profile."); if (observedTypes.isOnlyNonNumber()) return JITMathICInlineResult::DontGenerate; if (observedTypes.isOnlyInt32()) { jit.moveValueRegs(m_src, m_result); state.slowPathJumps.append(jit.branchIfNotInt32(m_src)); state.slowPathJumps.append(jit.branchTest32(CCallHelpers::Zero, m_src.payloadGPR(), CCallHelpers::TrustedImm32(0x7fffffff))); jit.neg32(m_result.payloadGPR()); #if USE(JSVALUE64) jit.boxInt32(m_result.payloadGPR(), m_result); #endif return JITMathICInlineResult::GeneratedFastPath; } if (observedTypes.isOnlyNumber()) { state.slowPathJumps.append(jit.branchIfInt32(m_src)); state.slowPathJumps.append(jit.branchIfNotNumber(m_src, m_scratchGPR)); #if USE(JSVALUE64) if (m_src.payloadGPR() != m_result.payloadGPR()) { jit.move(CCallHelpers::TrustedImm64(static_cast<int64_t>(1ull << 63)), m_result.payloadGPR()); jit.xor64(m_src.payloadGPR(), m_result.payloadGPR()); } else { jit.move(CCallHelpers::TrustedImm64(static_cast<int64_t>(1ull << 63)), m_scratchGPR); jit.xor64(m_scratchGPR, m_result.payloadGPR()); } #else jit.moveValueRegs(m_src, m_result); jit.xor32(CCallHelpers::TrustedImm32(1 << 31), m_result.tagGPR()); #endif return JITMathICInlineResult::GeneratedFastPath; } return JITMathICInlineResult::GenerateFullSnippet; }
bool JITNegGenerator::generateFastPath(CCallHelpers& jit, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, const ArithProfile* arithProfile, bool shouldEmitProfiling) { ASSERT(m_scratchGPR != m_src.payloadGPR()); ASSERT(m_scratchGPR != m_result.payloadGPR()); ASSERT(m_scratchGPR != InvalidGPRReg); #if USE(JSVALUE32_64) ASSERT(m_scratchGPR != m_src.tagGPR()); ASSERT(m_scratchGPR != m_result.tagGPR()); #endif jit.moveValueRegs(m_src, m_result); CCallHelpers::Jump srcNotInt = jit.branchIfNotInt32(m_src); // -0 should produce a double, and hence cannot be negated as an int. // The negative int32 0x80000000 doesn't have a positive int32 representation, and hence cannot be negated as an int. slowPathJumpList.append(jit.branchTest32(CCallHelpers::Zero, m_src.payloadGPR(), CCallHelpers::TrustedImm32(0x7fffffff))); jit.neg32(m_result.payloadGPR()); #if USE(JSVALUE64) jit.boxInt32(m_result.payloadGPR(), m_result); #endif endJumpList.append(jit.jump()); srcNotInt.link(&jit); slowPathJumpList.append(jit.branchIfNotNumber(m_src, m_scratchGPR)); // For a double, all we need to do is to invert the sign bit. #if USE(JSVALUE64) jit.move(CCallHelpers::TrustedImm64((int64_t)(1ull << 63)), m_scratchGPR); jit.xor64(m_scratchGPR, m_result.payloadGPR()); #else jit.xor32(CCallHelpers::TrustedImm32(1 << 31), m_result.tagGPR()); #endif // The flags of ArithNegate are basic in DFG. // We only need to know if we ever produced a number. if (shouldEmitProfiling && arithProfile && !arithProfile->lhsObservedType().sawNumber() && !arithProfile->didObserveDouble()) arithProfile->emitSetDouble(jit); return true; }
void JITRightShiftGenerator::generateFastPath(CCallHelpers& jit) { ASSERT(m_scratchGPR != InvalidGPRReg); ASSERT(m_scratchGPR != m_left.payloadGPR()); ASSERT(m_scratchGPR != m_right.payloadGPR()); #if USE(JSVALUE32_64) ASSERT(m_scratchGPR != m_left.tagGPR()); ASSERT(m_scratchGPR != m_right.tagGPR()); ASSERT(m_scratchFPR != InvalidFPRReg); #endif ASSERT(!m_leftOperand.isConstInt32() || !m_rightOperand.isConstInt32()); m_didEmitFastPath = true; if (m_rightOperand.isConstInt32()) { // Try to do (intVar >> intConstant). CCallHelpers::Jump notInt = jit.branchIfNotInt32(m_left); jit.moveValueRegs(m_left, m_result); int32_t shiftAmount = m_rightOperand.asConstInt32() & 0x1f; if (shiftAmount) { if (m_shiftType == SignedShift) jit.rshift32(CCallHelpers::Imm32(shiftAmount), m_result.payloadGPR()); else jit.urshift32(CCallHelpers::Imm32(shiftAmount), m_result.payloadGPR()); #if USE(JSVALUE64) jit.or64(GPRInfo::tagTypeNumberRegister, m_result.payloadGPR()); #endif } if (jit.supportsFloatingPointTruncate()) { m_endJumpList.append(jit.jump()); // Terminate the above case before emitting more code. // Try to do (doubleVar >> intConstant). notInt.link(&jit); m_slowPathJumpList.append(jit.branchIfNotNumber(m_left, m_scratchGPR)); jit.unboxDoubleNonDestructive(m_left, m_leftFPR, m_scratchGPR, m_scratchFPR); m_slowPathJumpList.append(jit.branchTruncateDoubleToInt32(m_leftFPR, m_scratchGPR)); if (shiftAmount) { if (m_shiftType == SignedShift) jit.rshift32(CCallHelpers::Imm32(shiftAmount), m_scratchGPR); else jit.urshift32(CCallHelpers::Imm32(shiftAmount), m_scratchGPR); } jit.boxInt32(m_scratchGPR, m_result); } else m_slowPathJumpList.append(notInt); } else { // Try to do (intConstant >> intVar) or (intVar >> intVar). m_slowPathJumpList.append(jit.branchIfNotInt32(m_right)); CCallHelpers::Jump notInt; if (m_leftOperand.isConstInt32()) { #if USE(JSVALUE32_64) jit.move(m_right.tagGPR(), m_result.tagGPR()); #endif jit.move(CCallHelpers::Imm32(m_leftOperand.asConstInt32()), m_result.payloadGPR()); } else { notInt = jit.branchIfNotInt32(m_left); jit.moveValueRegs(m_left, m_result); } if (m_shiftType == SignedShift) jit.rshift32(m_right.payloadGPR(), m_result.payloadGPR()); else jit.urshift32(m_right.payloadGPR(), m_result.payloadGPR()); #if USE(JSVALUE64) jit.or64(GPRInfo::tagTypeNumberRegister, m_result.payloadGPR()); #endif if (m_leftOperand.isConstInt32()) return; if (jit.supportsFloatingPointTruncate()) { m_endJumpList.append(jit.jump()); // Terminate the above case before emitting more code. // Try to do (doubleVar >> intVar). notInt.link(&jit); m_slowPathJumpList.append(jit.branchIfNotNumber(m_left, m_scratchGPR)); jit.unboxDoubleNonDestructive(m_left, m_leftFPR, m_scratchGPR, m_scratchFPR); m_slowPathJumpList.append(jit.branchTruncateDoubleToInt32(m_leftFPR, m_scratchGPR)); if (m_shiftType == SignedShift) jit.rshift32(m_right.payloadGPR(), m_scratchGPR); else jit.urshift32(m_right.payloadGPR(), m_scratchGPR); jit.boxInt32(m_scratchGPR, m_result); } else m_slowPathJumpList.append(notInt); } }