/*
 * Copyright (C) 2013-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. 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 "ResourceExhaustion.h"
#include <wtf/Atomics.h>
#include <wtf/DataLog.h>
#include <wtf/RawPointer.h>

namespace JSC {

#if USE(JSVALUE64)

namespace StructureIDTableInternal {
static constexpr bool verbose = false;
}

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_RESOURCE_AVAILABLE(m_size < newCapacity, StructureIDExhaustion, "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));

    dataLogLnIf(StructureIDTableInternal::verbose, "Allocated StructureID ", result, " for Structure ", RawPointer(structure));
    return result;
}

void StructureIDTable::deallocateID(Structure* structure, StructureID structureID)
{
    dataLogLnIf(StructureIDTableInternal::verbose, "Deallocated 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
