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

#include "config.h"
#include "StructureIDTable.h"

#include <wtf/Atomics.h>

namespace JSC {

#if USE(JSVALUE64)

StructureIDTable::StructureIDTable()
    : m_table(makeUniqueArray<StructureOrOffset>(s_initialSize))
    , m_size(1)
    , m_capacity(s_initialSize)
{
    // We pre-allocate the first offset so that the null Structure
    // can still be represented as the StructureID '0'.
    table()[0].encodedStructureBits = 0;

    makeFreeListFromRange(1, m_capacity - 1);
}

void StructureIDTable::makeFreeListFromRange(uint32_t first, uint32_t last)
{
    ASSERT(!m_firstFreeOffset);
    ASSERT(!m_lastFreeOffset);

    // Put all the new IDs on the free list sequentially.
    uint32_t head = first;
    uint32_t tail = last;
    for (uint32_t i = first; i < last; ++i)
        table()[i].offset = i + 1;
    table()[last].offset = 0;

    // Randomize the free list.
    uint32_t size = last - first + 1;
    uint32_t maxIterations = (size * 2) / 3;
    for (uint32_t count = 0; count < maxIterations; ++count) {
        // Move a random pick either to the head or the tail of the free list.
        uint32_t random = m_weakRandom.getUint32();
        uint32_t nodeBefore = first + (random % size);
        uint32_t pick = table()[nodeBefore].offset;
        if (pick) {
            uint32_t nodeAfter = table()[pick].offset;
            table()[nodeBefore].offset = nodeAfter;
            if ((random & 1) || !nodeAfter) {
                // Move to the head.
                table()[pick].offset = head;
                head = pick;
                if (!nodeAfter)
                    tail = nodeBefore;
            } else {
                // Move to the tail.
                table()[pick].offset = 0;
                table()[tail].offset = pick;
                tail = pick;
            }
        }
    }

    // Cut list in half and swap halves.
    uint32_t cut = first + (m_weakRandom.getUint32() % size);
    uint32_t afterCut = table()[cut].offset;
    if (afterCut) {
        table()[tail].offset = head;
        tail = cut;
        head = afterCut;
        table()[cut].offset = 0;
    }

    m_firstFreeOffset = head;
    m_lastFreeOffset = tail;
}

void StructureIDTable::resize(size_t newCapacity)
{
    if (newCapacity > s_maximumNumberOfStructures)
        newCapacity = s_maximumNumberOfStructures;

    // If m_size is already s_maximumNumberOfStructures, newCapacity becomes s_maximumNumberOfStructures in the above code.
    // In that case, we should crash because of exhaust of StructureIDs.
    RELEASE_ASSERT_WITH_MESSAGE(m_size < newCapacity, "Crash intentionally because of exhaust of StructureIDs.");

    // Create the new table.
    auto newTable = makeUniqueArray<StructureOrOffset>(newCapacity);

    // Copy the contents of the old table to the new table.
    memcpy(newTable.get(), table(), m_capacity * sizeof(StructureOrOffset));

    // Store fence to make sure we've copied everything before doing the swap.
    WTF::storeStoreFence();

    // Swap the old and new tables.
    swap(m_table, newTable);

    // Put the old table (now labeled as new) into the list of old tables.
    m_oldTables.append(WTFMove(newTable));

    // Update the capacity.
    m_capacity = newCapacity;

    makeFreeListFromRange(m_size, m_capacity - 1);
}

void StructureIDTable::flushOldTables()
{
    m_oldTables.clear();
}

StructureID StructureIDTable::allocateID(Structure* structure)
{
    if (UNLIKELY(!m_firstFreeOffset)) {
        RELEASE_ASSERT(m_capacity <= s_maximumNumberOfStructures);
        ASSERT(m_size == m_capacity);
        resize(m_capacity * 2);
        ASSERT(m_size < m_capacity);
        RELEASE_ASSERT(m_firstFreeOffset);
    }

    // entropyBits must not be zero. This ensures that if a corrupted
    // structureID is encountered (with incorrect entropyBits), the decoded
    // structure pointer for that ID will be always be a bad pointer with
    // high bits set.
    constexpr uint32_t entropyBitsMask = (1 << s_numberOfEntropyBits) - 1;
    uint32_t entropyBits = m_weakRandom.getUint32() & entropyBitsMask;
    if (UNLIKELY(!entropyBits)) {
        constexpr uint32_t numberOfValuesToPickFrom = entropyBitsMask;
        entropyBits = (m_weakRandom.getUint32() % numberOfValuesToPickFrom) + 1;
    }

    uint32_t structureIndex = m_firstFreeOffset;
    m_firstFreeOffset = table()[m_firstFreeOffset].offset;
    if (!m_firstFreeOffset)
        m_lastFreeOffset = 0;

    StructureID result = (structureIndex << s_numberOfEntropyBits) | entropyBits;
    table()[structureIndex].encodedStructureBits = encode(structure, result);
    m_size++;
    ASSERT(!isNuked(result));
    return result;
}

void StructureIDTable::deallocateID(Structure* structure, StructureID structureID)
{
    ASSERT(structureID != s_unusedID);
    uint32_t structureIndex = structureID >> s_numberOfEntropyBits;
    ASSERT(structureIndex && structureIndex < s_maximumNumberOfStructures);
    RELEASE_ASSERT(table()[structureIndex].encodedStructureBits == encode(structure, structureID));
    m_size--;
    if (!m_firstFreeOffset) {
        table()[structureIndex].offset = 0;
        m_firstFreeOffset = structureIndex;
        m_lastFreeOffset = structureIndex;
        return;
    }

    bool insertAtHead = m_weakRandom.getUint32() & 1;
    if (insertAtHead) {
        table()[structureIndex].offset = m_firstFreeOffset;
        m_firstFreeOffset = structureIndex;
    } else {
        table()[structureIndex].offset = 0;
        table()[m_lastFreeOffset].offset = structureIndex;
        m_lastFreeOffset = structureIndex;
    }
}

#endif // USE(JSVALUE64)

} // namespace JSC
