/*
 * Copyright (C) 2015-2019 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "JITDivGenerator.h"

#if ENABLE(JIT)

#include "ArithProfile.h"
#include "JSCJSValueInlines.h"
#include "MathCommon.h"

namespace JSC {

void JITDivGenerator::loadOperand(CCallHelpers& jit, SnippetOperand& opr, JSValueRegs oprRegs, FPRReg destFPR)
{
    if (opr.isConstInt32()) {
        // FIXME: this does not looks right.
        //     -On x86_64, CVTSI2SD has partial register stall on its FPR.
        //      A move or load might be a tiny bit larger but safer.
        //     -On ARM64 we also have FMOV that can load small immediates.
        jit.move(CCallHelpers::Imm32(opr.asConstInt32()), m_scratchGPR);
        jit.convertInt32ToDouble(m_scratchGPR, destFPR);
#if USE(JSVALUE64)
    } else if (opr.isConstDouble()) {
        jit.move(CCallHelpers::Imm64(opr.asRawBits()), m_scratchGPR);
        jit.move64ToDouble(m_scratchGPR, destFPR);
#endif
    } else {
        if (!opr.definitelyIsNumber())
            m_slowPathJumpList.append(jit.branchIfNotNumber(oprRegs, m_scratchGPR));
        CCallHelpers::Jump notInt32 = jit.branchIfNotInt32(oprRegs);
        jit.convertInt32ToDouble(oprRegs.payloadGPR(), destFPR);
        CCallHelpers::Jump oprIsLoaded = jit.jump();
        notInt32.link(&jit);
        jit.unboxDoubleNonDestructive(oprRegs, destFPR, m_scratchGPR, m_scratchFPR);
        oprIsLoaded.link(&jit);
    }
}

void JITDivGenerator::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_didEmitFastPath);
    if (!jit.supportsFloatingPoint())
        return;
    if (!m_leftOperand.mightBeNumber() || !m_rightOperand.mightBeNumber())
        return;

    ASSERT(!m_leftOperand.isConstInt32() || !m_rightOperand.isConstInt32());
    m_didEmitFastPath = true;
    loadOperand(jit, m_leftOperand, m_left, m_leftFPR);

#if USE(JSVALUE64)
    Optional<double> safeReciprocal;
    if (m_rightOperand.isConst()) {
        double constant = m_rightOperand.asConstNumber();
        safeReciprocal = safeReciprocalForDivByConst(constant);
    }

    if (safeReciprocal) {
        jit.move(CCallHelpers::Imm64(bitwise_cast<int64_t>(*safeReciprocal)), m_scratchGPR);
        jit.move64ToDouble(m_scratchGPR, m_rightFPR);

        jit.mulDouble(m_rightFPR, m_leftFPR);
    } else
#endif
    {
        loadOperand(jit, m_rightOperand, m_right, m_rightFPR);

        jit.divDouble(m_rightFPR, m_leftFPR);
    }

    // Is the result actually an integer? The DFG JIT would really like to know. If it's
    // not an integer, we set a bit. If this together with the slow case counter are below
    // threshold then the DFG JIT will compile this division with a speculation that the
    // remainder is zero.

    // As well, there are cases where a double result here would cause an important field
    // in the heap to sometimes have doubles in it, resulting in double predictions getting
    // propagated to a use site where it might cause damage (such as the index to an array
    // access). So if we are DFG compiling anything in the program, we want this code to
    // ensure that it produces integers whenever possible.
    
    CCallHelpers::JumpList notInt32;
    jit.branchConvertDoubleToInt32(m_leftFPR, m_scratchGPR, notInt32, m_scratchFPR);

    // If we've got an integer, we might as well make that the result of the division.
    jit.boxInt32(m_scratchGPR, m_result);
    m_endJumpList.append(jit.jump());

    notInt32.link(&jit);
#if USE(JSVALUE64)
    jit.moveDoubleTo64(m_leftFPR, m_scratchGPR);
    CCallHelpers::Jump notDoubleZero = jit.branchTest64(CCallHelpers::NonZero, m_scratchGPR);

    jit.move(GPRInfo::numberTagRegister, m_result.payloadGPR());
    m_endJumpList.append(jit.jump());

    notDoubleZero.link(&jit);
#endif
    if (m_arithProfile)
        jit.or32(CCallHelpers::TrustedImm32(ArithProfile::specialFastPathBit), CCallHelpers::AbsoluteAddress(m_arithProfile->addressOfBits()));
    jit.boxDouble(m_leftFPR, m_result);
}

} // namespace JSC

#endif // ENABLE(JIT)
