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

#if ENABLE(WEBASSEMBLY)

#include "WasmCallee.h"
#include "WasmCodeBlock.h"
#include "WasmMachineThreads.h"
#include <wtf/DataLog.h>
#include <wtf/Locker.h>
#include <wtf/StdLibExtras.h>

namespace JSC { namespace Wasm {

namespace WasmPlanInternal {
static constexpr bool verbose = false;
}

Plan::Plan(Context* context, Ref<ModuleInformation> info, CompletionTask&& task)
    : m_moduleInformation(WTFMove(info))
{
    m_completionTasks.append(std::make_pair(context, WTFMove(task)));
}
Plan::Plan(Context* context, CompletionTask&& task)
    : m_moduleInformation(ModuleInformation::create())
{
    m_completionTasks.append(std::make_pair(context, WTFMove(task)));
}

void Plan::runCompletionTasks()
{
    ASSERT(isComplete() && !hasWork());

    for (auto& task : m_completionTasks)
        task.second->run(*this);
    m_completionTasks.clear();
    m_completed.notifyAll();
}

void Plan::addCompletionTask(Context* context, CompletionTask&& task)
{
    Locker locker { m_lock };
    if (!isComplete())
        m_completionTasks.append(std::make_pair(context, WTFMove(task)));
    else
        task->run(*this);
}

void Plan::waitForCompletion()
{
    Locker locker { m_lock };
    if (!isComplete()) {
        m_completed.wait(m_lock);
    }
}

bool Plan::tryRemoveContextAndCancelIfLast(Context& context)
{
    Locker locker { m_lock };

    if (ASSERT_ENABLED) {
        // We allow the first completion task to not have a Context.
        for (unsigned i = 1; i < m_completionTasks.size(); ++i)
            ASSERT(m_completionTasks[i].first);
    }

    bool removedAnyTasks = false;
    m_completionTasks.removeAllMatching([&] (const std::pair<Context*, CompletionTask>& pair) {
        bool shouldRemove = pair.first == &context;
        removedAnyTasks |= shouldRemove;
        return shouldRemove;
    });

    if (!removedAnyTasks)
        return false;

    if (isComplete()) {
        // We trivially cancel anything that's completed.
        return true;
    }

    // FIXME: Make 0 index not so magical: https://bugs.webkit.org/show_bug.cgi?id=171395
    if (m_completionTasks.isEmpty() || (m_completionTasks.size() == 1 && !m_completionTasks[0].first)) {
        fail("WebAssembly Plan was cancelled. If you see this error message please file a bug at bugs.webkit.org!"_s);
        return true;
    }

    return false;
}

void Plan::fail(String&& errorMessage)
{
    if (failed())
        return;
    ASSERT(errorMessage);
    dataLogLnIf(WasmPlanInternal::verbose, "failing with message: ", errorMessage);
    m_errorMessage = WTFMove(errorMessage);
    complete();
}

#if ENABLE(WEBASSEMBLY_B3JIT)
void Plan::updateCallSitesToCallUs(CodeBlock& codeBlock, CodeLocationLabel<WasmEntryPtrTag> entrypoint, uint32_t functionIndex, uint32_t functionIndexSpace)
{
    HashMap<void*, CodeLocationLabel<WasmEntryPtrTag>> stagedCalls;
    auto stageRepatch = [&] (const Vector<UnlinkedWasmToWasmCall>& callsites) {
        for (auto& call : callsites) {
            if (call.functionIndexSpace == functionIndexSpace) {
                CodeLocationLabel<WasmEntryPtrTag> target = MacroAssembler::prepareForAtomicRepatchNearCallConcurrently(call.callLocation, entrypoint);
                stagedCalls.add(call.callLocation.dataLocation(), target);
            }
        }
    };
    for (unsigned i = 0; i < codeBlock.m_wasmToWasmCallsites.size(); ++i) {
        stageRepatch(codeBlock.m_wasmToWasmCallsites[i]);
        if (codeBlock.m_llintCallees) {
            LLIntCallee& llintCallee = codeBlock.m_llintCallees->at(i).get();
            if (JITCallee* replacementCallee = llintCallee.replacement(codeBlock.mode()))
                stageRepatch(replacementCallee->wasmToWasmCallsites());
            if (OMGForOSREntryCallee* osrEntryCallee = llintCallee.osrEntryCallee(codeBlock.mode()))
                stageRepatch(osrEntryCallee->wasmToWasmCallsites());
        }
        if (BBQCallee* bbqCallee = codeBlock.m_bbqCallees[i].get()) {
            if (OMGCallee* replacementCallee = bbqCallee->replacement())
                stageRepatch(replacementCallee->wasmToWasmCallsites());
            if (OMGForOSREntryCallee* osrEntryCallee = bbqCallee->osrEntryCallee())
                stageRepatch(osrEntryCallee->wasmToWasmCallsites());
        }
    }

    // It's important to make sure we do this before we make any of the code we just compiled visible. If we didn't, we could end up
    // where we are tiering up some function A to A' and we repatch some function B to call A' instead of A. Another CPU could see
    // the updates to B but still not have reset its cache of A', which would lead to all kinds of badness.
    resetInstructionCacheOnAllThreads();
    WTF::storeStoreFence(); // This probably isn't necessary but it's good to be paranoid.

    codeBlock.m_wasmIndirectCallEntryPoints[functionIndex] = entrypoint;

    auto repatchCalls = [&] (const Vector<UnlinkedWasmToWasmCall>& callsites) {
        for (auto& call : callsites) {
            dataLogLnIf(WasmPlanInternal::verbose, "Considering repatching call at: ", RawPointer(call.callLocation.dataLocation()), " that targets ", call.functionIndexSpace);
            if (call.functionIndexSpace == functionIndexSpace) {
                dataLogLnIf(WasmPlanInternal::verbose, "Repatching call at: ", RawPointer(call.callLocation.dataLocation()), " to ", RawPointer(entrypoint.executableAddress()));
                MacroAssembler::repatchNearCall(call.callLocation, stagedCalls.get(call.callLocation.dataLocation()));
            }
        }
    };

    for (unsigned i = 0; i < codeBlock.m_wasmToWasmCallsites.size(); ++i) {
        repatchCalls(codeBlock.m_wasmToWasmCallsites[i]);
        if (codeBlock.m_llintCallees) {
            LLIntCallee& llintCallee = codeBlock.m_llintCallees->at(i).get();
            if (JITCallee* replacementCallee = llintCallee.replacement(codeBlock.mode()))
                repatchCalls(replacementCallee->wasmToWasmCallsites());
            if (OMGForOSREntryCallee* osrEntryCallee = llintCallee.osrEntryCallee(codeBlock.mode()))
                repatchCalls(osrEntryCallee->wasmToWasmCallsites());
        }
        if (BBQCallee* bbqCallee = codeBlock.m_bbqCallees[i].get()) {
            if (OMGCallee* replacementCallee = bbqCallee->replacement())
                repatchCalls(replacementCallee->wasmToWasmCallsites());
            if (OMGForOSREntryCallee* osrEntryCallee = bbqCallee->osrEntryCallee())
                repatchCalls(osrEntryCallee->wasmToWasmCallsites());
        }
    }

}
#endif

Plan::~Plan() { }

} } // namespace JSC::Wasm

#endif // ENABLE(WEBASSEMBLY)
