/*
 * 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 "WasmSignature.h"

#if ENABLE(WEBASSEMBLY)

#include "WasmSignatureInlines.h"
#include <wtf/CommaPrinter.h>
#include <wtf/FastMalloc.h>
#include <wtf/StringPrintStream.h>

namespace JSC { namespace Wasm {

SignatureInformation* SignatureInformation::theOne { nullptr };
std::once_flag SignatureInformation::signatureInformationFlag;

String Signature::toString() const
{
    return WTF::toString(*this);
}

void Signature::dump(PrintStream& out) const
{
    {
        out.print("(");
        CommaPrinter comma;
        for (SignatureArgCount arg = 0; arg < argumentCount(); ++arg)
            out.print(comma, makeString(argument(arg).kind));
        out.print(")");
    }

    {
        CommaPrinter comma;
        out.print(" -> [");
        for (SignatureArgCount ret = 0; ret < returnCount(); ++ret)
            out.print(comma, makeString(returnType(ret).kind));
        out.print("]");
    }
}

static unsigned computeHash(size_t returnCount, const Type* returnTypes, size_t argumentCount, const Type* argumentTypes)
{
    unsigned accumulator = 0xa1bcedd8u;
    for (uint32_t i = 0; i < argumentCount; ++i) {
        accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<uint8_t>::hash(static_cast<uint8_t>(argumentTypes[i].kind)));
        accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<uint8_t>::hash(static_cast<uint8_t>(argumentTypes[i].nullable)));
        accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<unsigned>::hash(argumentTypes[i].index));
    }
    for (uint32_t i = 0; i < returnCount; ++i) {
        accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<uint8_t>::hash(static_cast<uint8_t>(returnTypes[i].kind)));
        accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<uint8_t>::hash(static_cast<uint8_t>(returnTypes[i].nullable)));
        accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<unsigned>::hash(returnTypes[i].index));
    }
    return accumulator;
}

unsigned Signature::hash() const
{
    return computeHash(returnCount(), storage(0), argumentCount(), storage(returnCount()));
}

RefPtr<Signature> Signature::tryCreate(SignatureArgCount returnCount, SignatureArgCount argumentCount)
{
    // We use WTF_MAKE_FAST_ALLOCATED for this class.
    auto result = tryFastMalloc(allocatedSize(returnCount, argumentCount));
    void* memory = nullptr;
    if (!result.getValue(memory))
        return nullptr;
    Signature* signature = new (NotNull, memory) Signature(returnCount, argumentCount);
    return adoptRef(signature);
}

SignatureInformation::SignatureInformation()
{
#define MAKE_THUNK_SIGNATURE(type, enc, str, val, _)                       \
    do {                                                                   \
        if (TypeKind::type != TypeKind::Void) {                            \
            RefPtr<Signature> sig = Signature::tryCreate(1, 0);            \
            sig->ref();                                                    \
            sig->getReturnType(0) = Types::type;                           \
            thunkSignatures[linearizeType(TypeKind::type)] = sig.get();    \
            m_signatureSet.add(SignatureHash { sig.releaseNonNull() });    \
        }                                                                  \
    } while (false);

    FOR_EACH_WASM_TYPE(MAKE_THUNK_SIGNATURE);

    // Make Void again because we don't use the one that has void in it.
    {
        RefPtr<Signature> sig = Signature::tryCreate(0, 0);
        sig->ref();
        thunkSignatures[linearizeType(TypeKind::Void)] = sig.get();
        m_signatureSet.add(SignatureHash { sig.releaseNonNull() });
    }
}



struct ParameterTypes {
    const Vector<Type, 1>& returnTypes;
    const Vector<Type>& argumentTypes;

    static unsigned hash(const ParameterTypes& params)
    {
        return computeHash(params.returnTypes.size(), params.returnTypes.data(), params.argumentTypes.size(), params.argumentTypes.data());
    }

    static bool equal(const SignatureHash& sig, const ParameterTypes& params)
    {
        if (sig.key->argumentCount() != params.argumentTypes.size())
            return false;
        if (sig.key->returnCount() != params.returnTypes.size())
            return false;

        for (unsigned i = 0; i < sig.key->argumentCount(); ++i) {
            if (sig.key->argument(i) != params.argumentTypes[i])
                return false;
        }

        for (unsigned i = 0; i < sig.key->returnCount(); ++i) {
            if (sig.key->returnType(i) != params.returnTypes[i])
                return false;
        }
        return true;
    }

    static void translate(SignatureHash& entry, const ParameterTypes& params, unsigned)
    {
        RefPtr<Signature> signature = Signature::tryCreate(params.returnTypes.size(), params.argumentTypes.size());
        RELEASE_ASSERT(signature);

        for (unsigned i = 0; i < params.returnTypes.size(); ++i)
            signature->getReturnType(i) = params.returnTypes[i];

        for (unsigned i = 0; i < params.argumentTypes.size(); ++i)
            signature->getArgument(i) = params.argumentTypes[i];

        entry.key = WTFMove(signature);
    }
};

RefPtr<Signature> SignatureInformation::signatureFor(const Vector<Type, 1>& results, const Vector<Type>& args)
{
    if constexpr (ASSERT_ENABLED) {
        ASSERT(!results.contains(Wasm::Types::Void));
        ASSERT(!args.contains(Wasm::Types::Void));
    }
    SignatureInformation& info = singleton();
    Locker locker { info.m_lock };

    auto addResult = info.m_signatureSet.template add<ParameterTypes>(ParameterTypes { results, args });
    return addResult.iterator->key;
}

void SignatureInformation::tryCleanup()
{
    SignatureInformation& info = singleton();
    Locker locker { info.m_lock };

    info.m_signatureSet.removeIf([&] (auto& hash) {
        const auto& signature = hash.key;
        return signature->refCount() == 1;
    });
}

} } // namespace JSC::Wasm

#endif // ENABLE(WEBASSEMBLY)
