/*
 * Copyright (C) 2016-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 "JITWorklist.h"

#if ENABLE(JIT)

#include "JIT.h"
#include "JSCInlines.h"
#include "VMInlines.h"

namespace JSC {

class JITWorklist::Plan : public ThreadSafeRefCounted<JITWorklist::Plan> {
public:
    Plan(CodeBlock* codeBlock, BytecodeIndex loopOSREntryBytecodeIndex)
        : m_codeBlock(codeBlock)
        , m_jit(codeBlock->vm(), codeBlock, loopOSREntryBytecodeIndex)
    {
        m_jit.doMainThreadPreparationBeforeCompile();
    }
    
    void compileInThread()
    {
        m_jit.compileWithoutLinking(JITCompilationCanFail);
        
        LockHolder locker(m_lock);
        m_isFinishedCompiling = true;
    }
    
    void finalize()
    {
        CompilationResult result = m_jit.link();
        switch (result) {
        case CompilationFailed:
            CODEBLOCK_LOG_EVENT(m_codeBlock, "delayJITCompile", ("compilation failed"));
            dataLogLnIf(Options::verboseOSR(), "    JIT compilation failed.");
            m_codeBlock->dontJITAnytimeSoon();
            m_codeBlock->m_didFailJITCompilation = true;
            return;
        case CompilationSuccessful:
            dataLogLnIf(Options::verboseOSR(), "    JIT compilation successful.");
            m_codeBlock->ownerExecutable()->installCode(m_codeBlock);
            m_codeBlock->jitSoon();
            return;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            return;
        }
    }
    
    CodeBlock* codeBlock() { return m_codeBlock; }
    VM& vm() { return m_codeBlock->vm(); }
    
    bool isFinishedCompiling()
    {
        LockHolder locker(m_lock);
        return m_isFinishedCompiling;
    }
    
    static void compileNow(CodeBlock* codeBlock, BytecodeIndex loopOSREntryBytecodeIndex)
    {
        Plan plan(codeBlock, loopOSREntryBytecodeIndex);
        plan.compileInThread();
        plan.finalize();
    }
    
private:
    CodeBlock* m_codeBlock;
    JIT m_jit;
    Lock m_lock;
    bool m_isFinishedCompiling { false };
};

class JITWorklist::Thread : public AutomaticThread {
public:
    Thread(const AbstractLocker& locker, JITWorklist& worklist)
        : AutomaticThread(locker, worklist.m_lock, worklist.m_condition.copyRef())
        , m_worklist(worklist)
    {
        m_worklist.m_numAvailableThreads++;
    }

    const char* name() const override
    {
#if OS(LINUX)
        return "JITWorker";
#else
        return "JIT Worklist Helper Thread";
#endif
    }
    
protected:
    PollResult poll(const AbstractLocker&) override
    {
        RELEASE_ASSERT(m_worklist.m_numAvailableThreads);
        
        if (m_worklist.m_queue.isEmpty())
            return PollResult::Wait;
        
        m_myPlans = WTFMove(m_worklist.m_queue);
        m_worklist.m_numAvailableThreads--;
        return PollResult::Work;
    }
    
    WorkResult work() override
    {
        RELEASE_ASSERT(!m_myPlans.isEmpty());
        
        for (RefPtr<Plan>& plan : m_myPlans) {
            plan->compileInThread();
            plan = nullptr;
            
            // Make sure that the main thread realizes that we just compiled something. Notifying
            // a condition is basically free if nobody is waiting.
            LockHolder locker(*m_worklist.m_lock);
            m_worklist.m_condition->notifyAll(locker);
        }
        
        m_myPlans.clear();
        
        LockHolder locker(*m_worklist.m_lock);
        m_worklist.m_numAvailableThreads++;
        return WorkResult::Continue;
    }
    
private:
    JITWorklist& m_worklist;
    Plans m_myPlans;
};

JITWorklist::JITWorklist()
    : m_lock(Box<Lock>::create())
    , m_condition(AutomaticThreadCondition::create())
{
    LockHolder locker(*m_lock);
    m_thread = new Thread(locker, *this);
}

JITWorklist::~JITWorklist()
{
    UNREACHABLE_FOR_PLATFORM();
}

bool JITWorklist::completeAllForVM(VM& vm)
{
    bool result = false;
    DeferGC deferGC(vm.heap);
    for (;;) {
        Vector<RefPtr<Plan>, 32> myPlans;
        {
            LockHolder locker(*m_lock);
            for (;;) {
                bool didFindUnfinishedPlan = false;
                m_plans.removeAllMatching(
                    [&] (RefPtr<Plan>& plan) {
                        if (&plan->vm() != &vm)
                            return false;
                        if (!plan->isFinishedCompiling()) {
                            didFindUnfinishedPlan = true;
                            return false;
                        }
                        myPlans.append(WTFMove(plan));
                        return true;
                    });
                
                // If we found plans then we should finalize them now.
                if (!myPlans.isEmpty())
                    break;
                
                // If we don't find plans, then we're either done or we need to wait, depending on
                // whether we found some unfinished plans.
                if (!didFindUnfinishedPlan)
                    return result;
                
                m_condition->wait(*m_lock);
            }
        }
        
        RELEASE_ASSERT(!myPlans.isEmpty());
        result = true;
        finalizePlans(myPlans);
    }
}

void JITWorklist::poll(VM& vm)
{
    DeferGC deferGC(vm.heap);
    Plans myPlans;
    {
        LockHolder locker(*m_lock);
        m_plans.removeAllMatching(
            [&] (RefPtr<Plan>& plan) {
                if (&plan->vm() != &vm)
                    return false;
                if (!plan->isFinishedCompiling())
                    return false;
                myPlans.append(WTFMove(plan));
                return true;
            });
    }
    
    finalizePlans(myPlans);
}

void JITWorklist::compileLater(CodeBlock* codeBlock, BytecodeIndex loopOSREntryBytecodeIndex)
{
    DeferGC deferGC(codeBlock->vm().heap);
    RELEASE_ASSERT(codeBlock->jitType() == JITType::InterpreterThunk);
    
    if (codeBlock->m_didFailJITCompilation) {
        codeBlock->dontJITAnytimeSoon();
        return;
    }
    
    if (!Options::useConcurrentJIT()) {
        Plan::compileNow(codeBlock, loopOSREntryBytecodeIndex);
        return;
    }
    
    codeBlock->jitSoon();

    {
        LockHolder locker(*m_lock);
        
        if (m_planned.contains(codeBlock))
            return;
        
        if (m_numAvailableThreads) {
            m_planned.add(codeBlock);
            RefPtr<Plan> plan = adoptRef(new Plan(codeBlock, loopOSREntryBytecodeIndex));
            m_plans.append(plan);
            m_queue.append(plan);
            m_condition->notifyAll(locker);
            return;
        }
    }

    // Compiling on the main thread if the helper thread isn't available is a defense against this
    // pathology:
    //
    // 1) Do something that is allowed to take a while, like load a giant piece of initialization
    //    code. This plans the compile of the init code, but doesn't finish it. It will take a
    //    while.
    //
    // 2) Do something that is supposed to be quick. Now all baseline compiles, and so all DFG and
    //    FTL compiles, of everything is blocked on the long-running baseline compile of that
    //    initialization code.
    //
    // The single-threaded concurrent JIT has this tendency to convoy everything while at the same
    // time postponing when it happens, which means that the convoy delays are less predictable.
    // This works around the issue. If the concurrent JIT thread is convoyed, we revert to main
    // thread compiles. This is probably not as good as if we had multiple JIT threads. Maybe we
    // can do that someday.
    Plan::compileNow(codeBlock, loopOSREntryBytecodeIndex);
}

void JITWorklist::compileNow(CodeBlock* codeBlock, BytecodeIndex loopOSREntryBytecodeIndex)
{
    VM& vm = codeBlock->vm();
    DeferGC deferGC(vm.heap);
    if (codeBlock->jitType() != JITType::InterpreterThunk)
        return;
    
    bool isPlanned;
    {
        LockHolder locker(*m_lock);
        isPlanned = m_planned.contains(codeBlock);
    }
    
    if (isPlanned) {
        RELEASE_ASSERT(Options::useConcurrentJIT());
        // This is expensive, but probably good enough.
        completeAllForVM(vm);
    }
    
    // Now it might be compiled!
    if (codeBlock->jitType() != JITType::InterpreterThunk)
        return;
    
    // We do this in case we had previously attempted, and then failed, to compile with the
    // baseline JIT.
    codeBlock->resetJITData();
    
    // OK, just compile it.
    JIT::compile(vm, codeBlock, JITCompilationMustSucceed, loopOSREntryBytecodeIndex);
    codeBlock->ownerExecutable()->installCode(codeBlock);
}

void JITWorklist::finalizePlans(Plans& myPlans)
{
    for (RefPtr<Plan>& plan : myPlans) {
        plan->finalize();
        
        LockHolder locker(*m_lock);
        m_planned.remove(plan->codeBlock());
    }
}

static JITWorklist* theGlobalJITWorklist { nullptr };

JITWorklist* JITWorklist::existingGlobalWorklistOrNull()
{
    return theGlobalJITWorklist;
}

JITWorklist& JITWorklist::ensureGlobalWorklist()
{
    static std::once_flag once;
    std::call_once(
        once,
        [] {
            auto* worklist = new JITWorklist();
            WTF::storeStoreFence();
            theGlobalJITWorklist = worklist;
        });
    return *theGlobalJITWorklist;
}

} // namespace JSC

#endif // ENABLE(JIT)

