/*
* Copyright (C) 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. ``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 <wtf/HashTraits.h>
#include <wtf/MathExtras.h>

namespace WTF {
class PrintStream;
}

namespace JSC {

class BytecodeIndex {
public:
    BytecodeIndex() = default;
    BytecodeIndex(WTF::HashTableDeletedValueType)
        : m_packedBits(deletedValue().asBits())
    {
    }

    explicit BytecodeIndex(uint32_t bytecodeOffset, uint8_t checkpoint = 0)
        : m_packedBits(pack(bytecodeOffset, checkpoint))
    {
        ASSERT(*this);
    }

    static constexpr uint32_t numberOfCheckpoints = 4;
    static_assert(hasOneBitSet(numberOfCheckpoints), "numberOfCheckpoints should be a power of 2");
    static constexpr uint32_t checkpointMask = numberOfCheckpoints - 1;
    static constexpr uint32_t checkpointShift = WTF::getMSBSetConstexpr(numberOfCheckpoints);

    uint32_t offset() const { return m_packedBits >> checkpointShift; }
    uint8_t checkpoint() const { return m_packedBits & checkpointMask; }
    uint32_t asBits() const { return m_packedBits; }

    unsigned hash() const { return WTF::intHash(m_packedBits); }
    static BytecodeIndex deletedValue() { return fromBits(invalidOffset - 1); }
    bool isHashTableDeletedValue() const { return *this == deletedValue(); }

    static BytecodeIndex fromBits(uint32_t bits);

    // Comparison operators.
    explicit operator bool() const { return m_packedBits != invalidOffset && m_packedBits != deletedValue().offset(); }
    bool operator ==(const BytecodeIndex& other) const { return asBits() == other.asBits(); }
    bool operator !=(const BytecodeIndex& other) const { return !(*this == other); }

    bool operator <(const BytecodeIndex& other) const { return asBits() < other.asBits(); }
    bool operator >(const BytecodeIndex& other) const { return asBits() > other.asBits(); }
    bool operator <=(const BytecodeIndex& other) const { return asBits() <= other.asBits(); }
    bool operator >=(const BytecodeIndex& other) const { return asBits() >= other.asBits(); }


    void dump(WTF::PrintStream&) const;

private:
    static constexpr uint32_t invalidOffset = std::numeric_limits<uint32_t>::max();

    static uint32_t pack(uint32_t bytecodeIndex, uint8_t checkpoint);

    uint32_t m_packedBits { invalidOffset };
};

inline uint32_t BytecodeIndex::pack(uint32_t bytecodeIndex, uint8_t checkpoint)
{
    ASSERT(checkpoint < numberOfCheckpoints);
    ASSERT((bytecodeIndex << checkpointShift) >> checkpointShift == bytecodeIndex);
    return bytecodeIndex << checkpointShift | checkpoint;
}

inline BytecodeIndex BytecodeIndex::fromBits(uint32_t bits)
{
    BytecodeIndex result;
    result.m_packedBits = bits;
    return result;
}

struct BytecodeIndexHash {
    static unsigned hash(const BytecodeIndex& key) { return key.hash(); }
    static bool equal(const BytecodeIndex& a, const BytecodeIndex& b) { return a == b; }
    static constexpr bool safeToCompareToEmptyOrDeleted = true;
};

} // namespace JSC

namespace WTF {

template<typename T> struct DefaultHash;
template<> struct DefaultHash<JSC::BytecodeIndex> {
    typedef JSC::BytecodeIndexHash Hash;
};

template<typename T> struct HashTraits;
template<> struct HashTraits<JSC::BytecodeIndex> : SimpleClassHashTraits<JSC::BytecodeIndex> {
    static constexpr bool emptyValueIsZero = false;
};

} // namespace WTF
