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

#include <wtf/DataLog.h>

namespace JSC {

HeapSnapshot::HeapSnapshot(HeapSnapshot* previousSnapshot)
    : m_previous(previousSnapshot)
{
}

HeapSnapshot::~HeapSnapshot()
{
}

void HeapSnapshot::appendNode(const HeapSnapshotNode& node)
{
    ASSERT(!m_finalized);
    ASSERT(!m_previous || !m_previous->nodeForCell(node.cell));

    m_nodes.append(node);
    m_filter.add(bitwise_cast<uintptr_t>(node.cell));
}

void HeapSnapshot::sweepCell(JSCell* cell)
{
    ASSERT(cell);

    if (m_finalized && !m_filter.ruleOut(bitwise_cast<uintptr_t>(cell))) {
        ASSERT_WITH_MESSAGE(!isEmpty(), "Our filter should have ruled us out if we are empty.");
        unsigned start = 0;
        unsigned end = m_nodes.size();
        while (start != end) {
            unsigned middle = start + ((end - start) / 2);
            HeapSnapshotNode& node = m_nodes[middle];
            if (cell == node.cell) {
                // Cells should always have 0 as low bits.
                // Mark this cell for removal by setting the low bit.
                ASSERT(!(reinterpret_cast<intptr_t>(node.cell) & CellToSweepTag));
                node.cell = reinterpret_cast<JSCell*>(reinterpret_cast<intptr_t>(node.cell) | CellToSweepTag);
                m_hasCellsToSweep = true;
                return;
            }
            if (cell < node.cell)
                end = middle;
            else
                start = middle + 1;
        }
    }

    if (m_previous)
        m_previous->sweepCell(cell);
}

void HeapSnapshot::shrinkToFit()
{
    if (m_finalized && m_hasCellsToSweep) {
        m_filter.reset();
        m_nodes.removeAllMatching(
            [&] (const HeapSnapshotNode& node) -> bool {
                bool willRemoveCell = bitwise_cast<intptr_t>(node.cell) & CellToSweepTag;
                if (!willRemoveCell)
                    m_filter.add(bitwise_cast<uintptr_t>(node.cell));
                return willRemoveCell;
            });
        m_nodes.shrinkToFit();
        m_hasCellsToSweep = false;
    }

    if (m_previous)
        m_previous->shrinkToFit();
}

void HeapSnapshot::finalize()
{
    ASSERT(!m_finalized);
    m_finalized = true;

    // Nodes are appended to the snapshot in identifier order.
    // Now that we have the complete list of nodes we will sort
    // them in a different order. Remember the range of identifiers
    // in this snapshot.
    if (!isEmpty()) {
        m_firstObjectIdentifier = m_nodes.first().identifier;
        m_lastObjectIdentifier = m_nodes.last().identifier;
    }

    std::sort(m_nodes.begin(), m_nodes.end(), [] (const HeapSnapshotNode& a, const HeapSnapshotNode& b) {
        return a.cell < b.cell;
    });

#ifndef NDEBUG
    // Assert there are no duplicates or nullptr cells.
    JSCell* previousCell = nullptr;
    for (auto& node : m_nodes) {
        ASSERT(node.cell);
        ASSERT(!(reinterpret_cast<intptr_t>(node.cell) & CellToSweepTag));
        if (node.cell == previousCell) {
            dataLog("Seeing same cell twice: ", RawPointer(previousCell), "\n");
            ASSERT(node.cell != previousCell);
        }
        previousCell = node.cell;
    }
#endif
}

std::optional<HeapSnapshotNode> HeapSnapshot::nodeForCell(JSCell* cell)
{
    ASSERT(m_finalized);

    if (!m_filter.ruleOut(bitwise_cast<uintptr_t>(cell))) {
        ASSERT_WITH_MESSAGE(!isEmpty(), "Our filter should have ruled us out if we are empty.");
        unsigned start = 0;
        unsigned end = m_nodes.size();
        while (start != end) {
            unsigned middle = start + ((end - start) / 2);
            HeapSnapshotNode& node = m_nodes[middle];
            if (cell == node.cell)
                return std::optional<HeapSnapshotNode>(node);
            if (cell < node.cell)
                end = middle;
            else
                start = middle + 1;
        }
    }

    if (m_previous)
        return m_previous->nodeForCell(cell);

    return std::nullopt;
}

std::optional<HeapSnapshotNode> HeapSnapshot::nodeForObjectIdentifier(unsigned objectIdentifier)
{
    if (isEmpty()) {
        if (m_previous)
            return m_previous->nodeForObjectIdentifier(objectIdentifier);
        return std::nullopt;
    }

    if (objectIdentifier > m_lastObjectIdentifier)
        return std::nullopt;

    if (objectIdentifier < m_firstObjectIdentifier) {
        if (m_previous)
            return m_previous->nodeForObjectIdentifier(objectIdentifier);
        return std::nullopt;
    }

    for (auto& node : m_nodes) {
        if (node.identifier == objectIdentifier)
            return std::optional<HeapSnapshotNode>(node);
    }

    return std::nullopt;
}

} // namespace JSC
