/*
 * Copyright (C) 2017-2021 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(WEBASSEMBLY)

#include "SlotVisitorMacros.h"
#include "WasmFormat.h"
#include "WasmLimits.h"
#include "WriteBarrier.h"
#include <wtf/MallocPtr.h>
#include <wtf/Ref.h>
#include <wtf/ThreadSafeRefCounted.h>

namespace JSC { namespace Wasm {

class Instance;
class FuncRefTable;

class Table : public ThreadSafeRefCounted<Table> {
    WTF_MAKE_NONCOPYABLE(Table);
    WTF_MAKE_FAST_ALLOCATED(Table);
public:
    static RefPtr<Table> tryCreate(uint32_t initial, std::optional<uint32_t> maximum, TableElementType);

    JS_EXPORT_PRIVATE ~Table() = default;

    std::optional<uint32_t> maximum() const { return m_maximum; }
    uint32_t length() const { return m_length; }

    static ptrdiff_t offsetOfLength() { return OBJECT_OFFSETOF(Table, m_length); }

    static uint32_t allocatedLength(uint32_t length);

    template<typename T> T* owner() const { return reinterpret_cast<T*>(m_owner); }
    void setOwner(JSObject* owner)
    {
        ASSERT(!m_owner);
        ASSERT(owner);
        m_owner = owner;
    }

    TableElementType type() const { return m_type; }
    bool isExternrefTable() const { return m_type == TableElementType::Externref; }
    bool isFuncrefTable() const { return m_type == TableElementType::Funcref; }
    Type wasmType() const;
    FuncRefTable* asFuncrefTable();

    static bool isValidLength(uint32_t length) { return length < maxTableEntries; }

    void clear(uint32_t);
    void set(uint32_t, JSValue);
    JSValue get(uint32_t) const;

    std::optional<uint32_t> grow(uint32_t delta, JSValue defaultValue);
    void copy(const Table* srcTable, uint32_t dstIndex, uint32_t srcIndex);

    DECLARE_VISIT_AGGREGATE;

protected:
    Table(uint32_t initial, std::optional<uint32_t> maximum, TableElementType = TableElementType::Externref);

    void setLength(uint32_t);

    uint32_t m_length;
    const TableElementType m_type;
    const std::optional<uint32_t> m_maximum;

    MallocPtr<WriteBarrier<Unknown>, VMMalloc> m_jsValues;
    JSObject* m_owner;
};

class FuncRefTable : public Table {
public:
    JS_EXPORT_PRIVATE ~FuncRefTable() = default;

    void setFunction(uint32_t, JSObject*, WasmToWasmImportableFunction, Instance*);
    const WasmToWasmImportableFunction& function(uint32_t) const;
    Instance* instance(uint32_t) const;

    void copyFunction(const FuncRefTable* srcTable, uint32_t dstIndex, uint32_t srcIndex);

    static ptrdiff_t offsetOfFunctions() { return OBJECT_OFFSETOF(FuncRefTable, m_importableFunctions); }
    static ptrdiff_t offsetOfInstances() { return OBJECT_OFFSETOF(FuncRefTable, m_instances); }

private:
    FuncRefTable(uint32_t initial, std::optional<uint32_t> maximum);

    MallocPtr<WasmToWasmImportableFunction, VMMalloc> m_importableFunctions;
    // call_indirect needs to do an Instance check to potentially context switch when calling a function to another instance. We can hold raw pointers to Instance here because the embedder ensures that Table keeps all the instances alive. We couldn't hold a Ref here because it would cause cycles.
    MallocPtr<Instance*, VMMalloc> m_instances;

    friend class Table;
};

} } // namespace JSC::Wasm

#endif // ENABLE(WEBASSEMBLY)
