/*
 * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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.
 */

#ifndef HandleHeap_h
#define HandleHeap_h

#include "BlockStack.h"
#include "Handle.h"
#include "SentinelLinkedList.h"
#include "SinglyLinkedList.h"

namespace JSC {

class HandleHeap;
class HeapRootMarker;
class JSGlobalData;
class JSValue;
class MarkStack;
class TypeCounter;

class WeakHandleOwner {
public:
    virtual ~WeakHandleOwner();
    virtual bool isReachableFromOpaqueRoots(Handle<Unknown>, void* context, MarkStack&);
    virtual void finalize(Handle<Unknown>, void* context);
};

class HandleHeap {
public:
    static HandleHeap* heapFor(HandleSlot);

    HandleHeap(JSGlobalData*);
    
    JSGlobalData* globalData();

    HandleSlot allocate();
    void deallocate(HandleSlot);

    void makeWeak(HandleSlot, WeakHandleOwner* = 0, void* context = 0);
    HandleSlot copyWeak(HandleSlot);

    void markStrongHandles(HeapRootMarker&);
    void markWeakHandles(HeapRootMarker&);
    void finalizeWeakHandles();

    void writeBarrier(HandleSlot, const JSValue&);

#if !ASSERT_DISABLED
    bool hasWeakOwner(HandleSlot, WeakHandleOwner*);
#endif

    unsigned protectedGlobalObjectCount();
    void protectedObjectTypeCounts(TypeCounter&);

private:
    class Node {
    public:
        Node(WTF::SentinelTag);
        Node(HandleHeap*);
        
        HandleSlot slot();
        HandleHeap* handleHeap();

        void makeWeak(WeakHandleOwner*, void* context);
        bool isWeak();
        
        WeakHandleOwner* weakOwner();
        void* weakOwnerContext();

        void setPrev(Node*);
        Node* prev();

        void setNext(Node*);
        Node* next();

    private:
        WeakHandleOwner* emptyWeakOwner();

        JSValue m_value;
        HandleHeap* m_handleHeap;
        WeakHandleOwner* m_weakOwner;
        void* m_weakOwnerContext;
        Node* m_prev;
        Node* m_next;
    };

    static HandleSlot toHandle(Node*);
    static Node* toNode(HandleSlot);

    void grow();
    
#if !ASSERT_DISABLED
    bool isValidWeakNode(Node*);
#endif

    JSGlobalData* m_globalData;
    BlockStack<Node> m_blockStack;

    SentinelLinkedList<Node> m_strongList;
    SentinelLinkedList<Node> m_weakList;
    SentinelLinkedList<Node> m_immediateList;
    SinglyLinkedList<Node> m_freeList;
    Node* m_nextToFinalize;
};

inline HandleHeap* HandleHeap::heapFor(HandleSlot handle)
{
    return toNode(handle)->handleHeap();
}

inline JSGlobalData* HandleHeap::globalData()
{
    return m_globalData;
}

inline HandleSlot HandleHeap::toHandle(Node* node)
{
    return reinterpret_cast<HandleSlot>(node);
}

inline HandleHeap::Node* HandleHeap::toNode(HandleSlot handle)
{
    return reinterpret_cast<Node*>(handle);
}

inline HandleSlot HandleHeap::allocate()
{
    if (m_freeList.isEmpty())
        grow();

    Node* node = m_freeList.pop();
    new (node) Node(this);
    m_immediateList.push(node);
    return toHandle(node);
}

inline void HandleHeap::deallocate(HandleSlot handle)
{
    Node* node = toNode(handle);
    if (node == m_nextToFinalize) {
        m_nextToFinalize = node->next();
        ASSERT(m_nextToFinalize->next());
    }

    SentinelLinkedList<Node>::remove(node);
    m_freeList.push(node);
}

inline HandleSlot HandleHeap::copyWeak(HandleSlot other)
{
    Node* node = toNode(allocate());
    node->makeWeak(toNode(other)->weakOwner(), toNode(other)->weakOwnerContext());
    writeBarrier(node->slot(), *other);
    *node->slot() = *other;
    return toHandle(node);
}

inline void HandleHeap::makeWeak(HandleSlot handle, WeakHandleOwner* weakOwner, void* context)
{
    Node* node = toNode(handle);
    node->makeWeak(weakOwner, context);

    SentinelLinkedList<Node>::remove(node);
    if (!*handle || !handle->isCell()) {
        m_immediateList.push(node);
        return;
    }

    m_weakList.push(node);
}

#if !ASSERT_DISABLED
inline bool HandleHeap::hasWeakOwner(HandleSlot handle, WeakHandleOwner* weakOwner)
{
    return toNode(handle)->weakOwner() == weakOwner;
}
#endif

inline HandleHeap::Node::Node(HandleHeap* handleHeap)
    : m_handleHeap(handleHeap)
    , m_weakOwner(0)
    , m_weakOwnerContext(0)
{
}

inline HandleHeap::Node::Node(WTF::SentinelTag)
    : m_handleHeap(0)
    , m_weakOwner(0)
    , m_weakOwnerContext(0)
{
}

inline HandleSlot HandleHeap::Node::slot()
{
    return &m_value;
}

inline HandleHeap* HandleHeap::Node::handleHeap()
{
    return m_handleHeap;
}

inline void HandleHeap::Node::makeWeak(WeakHandleOwner* weakOwner, void* context)
{
    m_weakOwner = weakOwner ? weakOwner : emptyWeakOwner();
    m_weakOwnerContext = context;
}

inline bool HandleHeap::Node::isWeak()
{
    return m_weakOwner; // True for emptyWeakOwner().
}

inline WeakHandleOwner* HandleHeap::Node::weakOwner()
{
    return m_weakOwner == emptyWeakOwner() ? 0 : m_weakOwner; // 0 for emptyWeakOwner().
}

inline void* HandleHeap::Node::weakOwnerContext()
{
    ASSERT(weakOwner());
    return m_weakOwnerContext;
}

inline void HandleHeap::Node::setPrev(Node* prev)
{
    m_prev = prev;
}

inline HandleHeap::Node* HandleHeap::Node::prev()
{
    return m_prev;
}

inline void HandleHeap::Node::setNext(Node* next)
{
    m_next = next;
}

inline HandleHeap::Node* HandleHeap::Node::next()
{
    return m_next;
}

// Sentinel to indicate that a node is weak, but its owner has no meaningful
// callbacks. This allows us to optimize by skipping such nodes.
inline WeakHandleOwner* HandleHeap::Node::emptyWeakOwner()
{
    return reinterpret_cast<WeakHandleOwner*>(-1);
}

}

#endif
