/*
 * Copyright (C) 2012-2018 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. 
 */

#pragma once

#if ENABLE(DFG_JIT)

#include "DFGSilentRegisterSavePlan.h"
#include "DFGSpeculativeJIT.h"
#include <wtf/FastMalloc.h>
#include <wtf/FunctionTraits.h>

namespace JSC { namespace DFG {

class SlowPathGenerator {
    WTF_MAKE_FAST_ALLOCATED;
public:
    SlowPathGenerator(SpeculativeJIT* jit)
        : m_currentNode(jit->m_currentNode)
        , m_streamIndex(jit->m_stream.size())
        , m_origin(jit->m_origin) 
    {
    }
    virtual ~SlowPathGenerator() { }
    void generate(SpeculativeJIT* jit)
    {
        m_label = jit->m_jit.label();
        jit->m_currentNode = m_currentNode;
        jit->m_outOfLineStreamIndex = m_streamIndex;
        jit->m_origin = m_origin;
        generateInternal(jit);
        jit->m_outOfLineStreamIndex = std::nullopt;
        if (ASSERT_ENABLED)
            jit->m_jit.abortWithReason(DFGSlowPathGeneratorFellThrough);
    }
    MacroAssembler::Label label() const { return m_label; }
    virtual MacroAssembler::Call call() const
    {
        RELEASE_ASSERT_NOT_REACHED(); // By default slow path generators don't have a call.
        return MacroAssembler::Call();
    }

    const NodeOrigin& origin() const  { return m_origin; }
    Node* currentNode() const { return m_currentNode; }

protected:
    virtual void generateInternal(SpeculativeJIT*) = 0;
    Node* m_currentNode;
    MacroAssembler::Label m_label;
    unsigned m_streamIndex;
    NodeOrigin m_origin;
};

template<typename JumpType>
class JumpingSlowPathGenerator : public SlowPathGenerator {
public:
    JumpingSlowPathGenerator(JumpType from, SpeculativeJIT* jit)
        : SlowPathGenerator(jit)
        , m_from(from)
        , m_to(jit->m_jit.label())
    {
    }
    
protected:
    void linkFrom(SpeculativeJIT* jit)
    {
        m_from.link(&jit->m_jit);
    }
    
    void jumpTo(SpeculativeJIT* jit)
    {
        jit->m_jit.jump().linkTo(m_to, &jit->m_jit);
    }

    JumpType m_from;
    MacroAssembler::Label m_to;
};

enum class ExceptionCheckRequirement : uint8_t {
    CheckNeeded,
    CheckNotNeeded
};

template<typename JumpType, typename ResultType>
class CallSlowPathGenerator : public JumpingSlowPathGenerator<JumpType> {
public:
    CallSlowPathGenerator(
        JumpType from, SpeculativeJIT* jit,
        SpillRegistersMode spillMode, ExceptionCheckRequirement requirement, ResultType result)
        : JumpingSlowPathGenerator<JumpType>(from, jit)
        , m_spillMode(spillMode)
        , m_exceptionCheckRequirement(requirement)
        , m_result(result)
    {
        if (m_spillMode == NeedToSpill)
            jit->silentSpillAllRegistersImpl(false, m_plans, extractResult(result));
    }
    
    MacroAssembler::Call call() const override
    {
        return m_call;
    }
    
protected:
    void setUp(SpeculativeJIT* jit)
    {
        this->linkFrom(jit);
        if (m_spillMode == NeedToSpill) {
            for (unsigned i = 0; i < m_plans.size(); ++i)
                jit->silentSpill(m_plans[i]);
        }
    }
    
    void recordCall(MacroAssembler::Call call)
    {
        m_call = call;
    }
    
    void tearDown(SpeculativeJIT* jit)
    {
        if (m_spillMode == NeedToSpill) {
            for (unsigned i = m_plans.size(); i--;)
                jit->silentFill(m_plans[i]);
        }
        if (m_exceptionCheckRequirement == ExceptionCheckRequirement::CheckNeeded)
            jit->m_jit.exceptionCheck();
        this->jumpTo(jit);
    }

    MacroAssembler::Call m_call;
    SpillRegistersMode m_spillMode;
    ExceptionCheckRequirement m_exceptionCheckRequirement;
    ResultType m_result;
    Vector<SilentRegisterSavePlan, 2> m_plans;
};

template<typename JumpType, typename FunctionType, typename ResultType, typename... Arguments>
class CallResultAndArgumentsSlowPathGenerator final : public CallSlowPathGenerator<JumpType, ResultType> {
public:
    CallResultAndArgumentsSlowPathGenerator(
        JumpType from, SpeculativeJIT* jit, FunctionType function,
        SpillRegistersMode spillMode, ExceptionCheckRequirement requirement, ResultType result, Arguments... arguments)
        : CallSlowPathGenerator<JumpType, ResultType>(from, jit, spillMode, requirement, result)
        , m_function(function)
        , m_arguments(std::forward<Arguments>(arguments)...)
    {
    }

private:
    template<size_t... ArgumentsIndex>
    void unpackAndGenerate(SpeculativeJIT* jit, std::index_sequence<ArgumentsIndex...>)
    {
        this->setUp(jit);
        if constexpr (std::is_same<ResultType, NoResultTag>::value)
            this->recordCall(jit->callOperation(this->m_function, std::get<ArgumentsIndex>(m_arguments)...));
        else
            this->recordCall(jit->callOperation(this->m_function, extractResult(this->m_result), std::get<ArgumentsIndex>(m_arguments)...));
        this->tearDown(jit);
    }

    void generateInternal(SpeculativeJIT* jit) final
    {
        unpackAndGenerate(jit, std::make_index_sequence<std::tuple_size<std::tuple<Arguments...>>::value>());
    }

    FunctionType m_function;
    std::tuple<Arguments...> m_arguments;
};

template<typename JumpType, typename FunctionType, typename ResultType, typename... Arguments>
inline std::unique_ptr<SlowPathGenerator> slowPathCall(
    JumpType from, SpeculativeJIT* jit, FunctionType function,
    SpillRegistersMode spillMode, ExceptionCheckRequirement requirement,
    ResultType result, Arguments... arguments)
{
    return makeUnique<CallResultAndArgumentsSlowPathGenerator<JumpType, FunctionType, ResultType, Arguments...>>(
        from, jit, function, spillMode, requirement, result, arguments...);
}

template<typename JumpType, typename FunctionType, typename ResultType, typename... Arguments>
inline std::unique_ptr<SlowPathGenerator> slowPathCall(
    JumpType from, SpeculativeJIT* jit, FunctionType function,
    ResultType result, Arguments... arguments)
{
    return slowPathCall(
        from, jit, function, NeedToSpill, ExceptionCheckRequirement::CheckNeeded, result, arguments...);
}

template<typename JumpType, typename DestinationType, typename SourceType, unsigned numberOfAssignments>
class AssigningSlowPathGenerator final : public JumpingSlowPathGenerator<JumpType> {
public:
    AssigningSlowPathGenerator(
        JumpType from, SpeculativeJIT* jit,
        DestinationType destination[numberOfAssignments],
        SourceType source[numberOfAssignments])
        : JumpingSlowPathGenerator<JumpType>(from, jit)
    {
        for (unsigned i = numberOfAssignments; i--;) {
            m_destination[i] = destination[i];
            m_source[i] = source[i];
        }
    }

private:
    void generateInternal(SpeculativeJIT* jit) final
    {
        this->linkFrom(jit);
        for (unsigned i = numberOfAssignments; i--;)
            jit->m_jit.move(m_source[i], m_destination[i]);
        this->jumpTo(jit);
    }

    DestinationType m_destination[numberOfAssignments];
    SourceType m_source[numberOfAssignments];
};

template<typename JumpType, typename DestinationType, typename SourceType, unsigned numberOfAssignments>
inline std::unique_ptr<SlowPathGenerator> slowPathMove(
    JumpType from, SpeculativeJIT* jit, SourceType source[numberOfAssignments], DestinationType destination[numberOfAssignments])
{
    return makeUnique<AssigningSlowPathGenerator<JumpType, DestinationType, SourceType, numberOfAssignments>>(
        from, jit, destination, source);
}

template<typename JumpType, typename DestinationType, typename SourceType>
inline std::unique_ptr<SlowPathGenerator> slowPathMove(
    JumpType from, SpeculativeJIT* jit, SourceType source, DestinationType destination)
{
    SourceType sourceArray[1] = { source };
    DestinationType destinationArray[1] = { destination };
    return makeUnique<AssigningSlowPathGenerator<JumpType, DestinationType, SourceType, 1>>(
        from, jit, destinationArray, sourceArray);
}

template<typename JumpType, typename DestinationType, typename SourceType>
inline std::unique_ptr<SlowPathGenerator> slowPathMove(
    JumpType from, SpeculativeJIT* jit, SourceType source1, DestinationType destination1, SourceType source2, DestinationType destination2)
{
    SourceType sourceArray[2] = { source1, source2 };
    DestinationType destinationArray[2] = { destination1, destination2 };
    return makeUnique<AssigningSlowPathGenerator<JumpType, DestinationType, SourceType, 2>>(
        from, jit, destinationArray, sourceArray);
}

template<typename JumpType, typename FunctionType, typename ResultType, typename... Arguments>
class CallResultAndArgumentsSlowPathICGenerator final : public CallSlowPathGenerator<JumpType, ResultType> {
public:
    CallResultAndArgumentsSlowPathICGenerator(
        JumpType from, SpeculativeJIT* jit, StructureStubInfo* stubInfo, GPRReg stubInfoGPR, CCallHelpers::Address slowPathOperationAddress, FunctionType function,
        SpillRegistersMode spillMode, ExceptionCheckRequirement requirement, ResultType result, Arguments... arguments)
        : CallSlowPathGenerator<JumpType, ResultType>(from, jit, spillMode, requirement, result)
        , m_stubInfoGPR(stubInfoGPR)
        , m_slowPathOperationAddress(slowPathOperationAddress)
        , m_function(function)
        , m_arguments(std::forward<Arguments>(arguments)...)
        , m_stubInfo(stubInfo)
    {
    }

private:
    template<size_t... ArgumentsIndex>
    void unpackAndGenerate(SpeculativeJIT* jit, std::index_sequence<ArgumentsIndex...>)
    {
        ASSERT(JITCode::useDataIC(JITType::DFGJIT));
        this->setUp(jit);
        m_stubInfo->m_slowOperation = m_function;
        jit->m_jit.move(CCallHelpers::TrustedImmPtr(m_stubInfo), m_stubInfoGPR);
        if constexpr (std::is_same<ResultType, NoResultTag>::value)
            jit->callOperation<FunctionType>(m_slowPathOperationAddress, std::get<ArgumentsIndex>(m_arguments)...);
        else
            jit->callOperation<FunctionType>(m_slowPathOperationAddress, extractResult(this->m_result), std::get<ArgumentsIndex>(m_arguments)...);
        this->tearDown(jit);
    }

    void generateInternal(SpeculativeJIT* jit) final
    {
        unpackAndGenerate(jit, std::make_index_sequence<std::tuple_size<std::tuple<Arguments...>>::value>());
    }

    GPRReg m_stubInfoGPR;
    CCallHelpers::Address m_slowPathOperationAddress;
    FunctionType m_function;
    std::tuple<Arguments...> m_arguments;
    StructureStubInfo* m_stubInfo;
};

template<typename JumpType, typename FunctionType, typename ResultType, typename... Arguments>
inline std::unique_ptr<SlowPathGenerator> slowPathICCall(
    JumpType from, SpeculativeJIT* jit, StructureStubInfo* stubInfo, GPRReg stubInfoGPR, CCallHelpers::Address slowPathOperationAddress, FunctionType function,
    SpillRegistersMode spillMode, ExceptionCheckRequirement requirement,
    ResultType result, Arguments... arguments)
{
    return makeUnique<CallResultAndArgumentsSlowPathICGenerator<JumpType, FunctionType, ResultType, Arguments...>>(from, jit, stubInfo, stubInfoGPR, slowPathOperationAddress, function, spillMode, requirement, result, arguments...);
}

template<typename JumpType, typename FunctionType, typename ResultType, typename... Arguments>
inline std::unique_ptr<SlowPathGenerator> slowPathICCall(
    JumpType from, SpeculativeJIT* jit, StructureStubInfo* stubInfo, GPRReg stubInfoGPR, CCallHelpers::Address slowPathOperationAddress, FunctionType function,
    ResultType result, Arguments... arguments)
{
    return slowPathICCall(from, jit, stubInfo, stubInfoGPR, slowPathOperationAddress, function, NeedToSpill, ExceptionCheckRequirement::CheckNeeded, result, arguments...);
}

} } // namespace JSC::DFG

#endif // ENABLD(DFG_JIT)
