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

#include "AbstractSlotVisitor.h"
#include "Heap.h"
#include "WeakInlines.h"
#include "WriteBarrier.h"

namespace JSC {

using ReferrerToken = AbstractSlotVisitor::ReferrerToken;

inline ReferrerToken::ReferrerToken(HeapCell* cell)
    : m_bits(bitwise_cast<uintptr_t>(cell) | HeapCellToken)
{
}

inline ReferrerToken::ReferrerToken(OpaqueRootTag, void* opaqueRoot)
    : m_bits(bitwise_cast<uintptr_t>(opaqueRoot) | OpaqueRootToken)
{
    ASSERT(opaqueRoot);
}

inline ReferrerToken::ReferrerToken(RootMarkReason reason)
    : m_bits((static_cast<uintptr_t>(reason) << tokenTypeShift) | RootMarkReasonToken)
{
}

inline HeapCell* ReferrerToken::asCell() const
{
    return isHeapCell() ? bitwise_cast<HeapCell*>(m_bits & ~tokenTypeMask) : nullptr;
}

inline void* ReferrerToken::asOpaqueRoot() const
{
    return isOpaqueRoot() ? bitwise_cast<HeapCell*>(m_bits & ~tokenTypeMask) : nullptr;
}

inline RootMarkReason ReferrerToken::asRootMarkReason() const
{
    return isRootMarkReason() ? static_cast<RootMarkReason>(m_bits >> tokenTypeShift) : RootMarkReason::None;
}

inline AbstractSlotVisitor::ReferrerContext::ReferrerContext(AbstractSlotVisitor& visitor, ReferrerToken referrer)
    : m_visitor(visitor)
    , m_referrer(referrer)
{
    m_previous = m_visitor.m_context;
    if (m_previous) {
        // An OpaqueRoot contexts can only be on the leaf.
        RELEASE_ASSERT(!m_previous->m_isOpaqueRootContext);
    }
    m_visitor.m_context = this;
}

inline AbstractSlotVisitor::ReferrerContext::ReferrerContext(AbstractSlotVisitor& visitor, AbstractSlotVisitor::OpaqueRootTag)
    : m_visitor(visitor)
    , m_isOpaqueRootContext(true)
{
    m_previous = m_visitor.m_context;
    if (m_previous) {
        // An OpaqueRoot contexts can only be on the leaf.
        RELEASE_ASSERT(!m_previous->m_isOpaqueRootContext);
    }
    m_visitor.m_context = this;
}

inline AbstractSlotVisitor::ReferrerContext::~ReferrerContext()
{
    m_visitor.m_context = m_previous;
}

inline AbstractSlotVisitor::AbstractSlotVisitor(Heap& heap, CString codeName, ConcurrentPtrHashSet& opaqueRoots)
    : m_heap(heap)
    , m_codeName(codeName)
    , m_opaqueRoots(opaqueRoots)
{
}

inline Heap* AbstractSlotVisitor::heap() const
{
    return &m_heap;
}

inline VM& AbstractSlotVisitor::vm()
{
    return m_heap.vm();
}

inline const VM& AbstractSlotVisitor::vm() const
{
    return m_heap.vm();
}

inline bool AbstractSlotVisitor::addOpaqueRoot(void* ptr)
{
    if (!ptr)
        return false;
    if (m_ignoreNewOpaqueRoots)
        return false;
    if (!m_opaqueRoots.add(ptr))
        return false;
    if (UNLIKELY(m_needsExtraOpaqueRootHandling))
        didAddOpaqueRoot(ptr);
    m_visitCount++;
    return true;
}

inline bool AbstractSlotVisitor::containsOpaqueRoot(void* ptr) const
{
    bool found = m_opaqueRoots.contains(ptr);
    if (UNLIKELY(found && m_needsExtraOpaqueRootHandling)) {
        auto* nonConstThis = const_cast<AbstractSlotVisitor*>(this);
        nonConstThis->didFindOpaqueRoot(ptr);
    }
    return found;
}

template<typename T>
ALWAYS_INLINE void AbstractSlotVisitor::append(const Weak<T>& weak)
{
    appendUnbarriered(weak.get());
}

template<typename T, typename Traits>
ALWAYS_INLINE void AbstractSlotVisitor::append(const WriteBarrierBase<T, Traits>& slot)
{
    appendUnbarriered(slot.get());
}

template<typename T, typename Traits>
ALWAYS_INLINE void AbstractSlotVisitor::appendHidden(const WriteBarrierBase<T, Traits>& slot)
{
    appendHiddenUnbarriered(slot.get());
}

ALWAYS_INLINE void AbstractSlotVisitor::appendHiddenUnbarriered(JSValue value)
{
    if (value.isCell())
        appendHiddenUnbarriered(value.asCell());
}

template<typename Iterator>
ALWAYS_INLINE void AbstractSlotVisitor::append(Iterator begin, Iterator end)
{
    for (auto it = begin; it != end; ++it)
        append(*it);
}

ALWAYS_INLINE void AbstractSlotVisitor::appendValues(const WriteBarrierBase<Unknown>* barriers, size_t count)
{
    for (size_t i = 0; i < count; ++i)
        append(barriers[i]);
}

ALWAYS_INLINE void AbstractSlotVisitor::appendValuesHidden(const WriteBarrierBase<Unknown>* barriers, size_t count)
{
    for (size_t i = 0; i < count; ++i)
        appendHidden(barriers[i]);
}

ALWAYS_INLINE void AbstractSlotVisitor::appendUnbarriered(JSValue value)
{
    if (value.isCell())
        appendUnbarriered(value.asCell());
}

ALWAYS_INLINE void AbstractSlotVisitor::appendUnbarriered(JSValue* slot, size_t count)
{
    for (size_t i = count; i--;)
        appendUnbarriered(slot[i]);
}

ALWAYS_INLINE ReferrerToken AbstractSlotVisitor::referrer() const
{
    if (!m_context)
        return nullptr;
    return m_context->referrer();
}

ALWAYS_INLINE void AbstractSlotVisitor::reset()
{
    m_visitCount = 0;
}

} // namespace JSC
