/*
 * Copyright (C) 2008-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 "IndexingType.h"
#include "WeakGCMap.h"
#include <wtf/HashFunctions.h>
#include <wtf/text/UniquedStringImpl.h>

namespace JSC {

class JSCell;
class Structure;

using TransitionPropertyAttributes = uint8_t;

enum class TransitionKind : uint8_t {
    Unknown,
    PropertyAddition,
    PropertyDeletion,
    PropertyAttributeChange,

    // Support for transitions not related to properties.
    // If any of these are used, the string portion of the key should be 0.
    AllocateUndecided,
    AllocateInt32,
    AllocateDouble,
    AllocateContiguous,
    AllocateArrayStorage,
    AllocateSlowPutArrayStorage,
    SwitchToSlowPutArrayStorage,
    AddIndexedAccessors,
    PreventExtensions,
    Seal,
    Freeze
};

static constexpr auto FirstNonPropertyTransitionKind = TransitionKind::AllocateUndecided;

inline bool changesIndexingType(TransitionKind transition)
{
    switch (transition) {
    case TransitionKind::AllocateUndecided:
    case TransitionKind::AllocateInt32:
    case TransitionKind::AllocateDouble:
    case TransitionKind::AllocateContiguous:
    case TransitionKind::AllocateArrayStorage:
    case TransitionKind::AllocateSlowPutArrayStorage:
    case TransitionKind::SwitchToSlowPutArrayStorage:
    case TransitionKind::AddIndexedAccessors:
        return true;
    default:
        return false;
    }
}

inline IndexingType newIndexingType(IndexingType oldType, TransitionKind transition)
{
    switch (transition) {
    case TransitionKind::AllocateUndecided:
        ASSERT(!hasIndexedProperties(oldType));
        return oldType | UndecidedShape;
    case TransitionKind::AllocateInt32:
        ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || oldType == CopyOnWriteArrayWithInt32);
        return (oldType & ~IndexingShapeAndWritabilityMask) | Int32Shape;
    case TransitionKind::AllocateDouble:
        ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || oldType == CopyOnWriteArrayWithDouble);
        return (oldType & ~IndexingShapeAndWritabilityMask) | DoubleShape;
    case TransitionKind::AllocateContiguous:
        ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType) || oldType == CopyOnWriteArrayWithContiguous);
        return (oldType & ~IndexingShapeAndWritabilityMask) | ContiguousShape;
    case TransitionKind::AllocateArrayStorage:
        ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType) || hasContiguous(oldType));
        return (oldType & ~IndexingShapeAndWritabilityMask) | ArrayStorageShape;
    case TransitionKind::AllocateSlowPutArrayStorage:
        ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType) || hasContiguous(oldType));
        return (oldType & ~IndexingShapeAndWritabilityMask) | SlowPutArrayStorageShape;
    case TransitionKind::SwitchToSlowPutArrayStorage:
        ASSERT(hasArrayStorage(oldType));
        return (oldType & ~IndexingShapeAndWritabilityMask) | SlowPutArrayStorageShape;
    case TransitionKind::AddIndexedAccessors:
        return oldType | MayHaveIndexedAccessors;
    default:
        return oldType;
    }
}

inline bool preventsExtensions(TransitionKind transition)
{
    switch (transition) {
    case TransitionKind::PreventExtensions:
    case TransitionKind::Seal:
    case TransitionKind::Freeze:
        return true;
    default:
        return false;
    }
}

inline bool setsDontDeleteOnAllProperties(TransitionKind transition)
{
    switch (transition) {
    case TransitionKind::Seal:
    case TransitionKind::Freeze:
        return true;
    default:
        return false;
    }
}

inline bool setsReadOnlyOnNonAccessorProperties(TransitionKind transition)
{
    switch (transition) {
    case TransitionKind::Freeze:
        return true;
    default:
        return false;
    }
}

class StructureTransitionTable {
    static constexpr intptr_t UsingSingleSlotFlag = 1;

    
#if CPU(ADDRESS64)
    struct Hash {
        // Logically, Key is a tuple of (1) UniquedStringImpl*, (2) unsigned attributes, and (3) transitionKind.
        struct Key {
            friend struct Hash;
            static_assert(WTF_OS_CONSTANT_EFFECTIVE_ADDRESS_WIDTH <= 48);
            static constexpr unsigned attributesShift = 48;
            static constexpr unsigned transitionKindShift = 56;
            static constexpr uintptr_t stringMask = (1ULL << attributesShift) - 1;
            static constexpr uintptr_t hashTableDeletedValue = 0x2;
            static_assert(sizeof(TransitionPropertyAttributes) * 8 <= 8);
            static_assert(sizeof(TransitionKind) * 8 <= 8);
            static_assert(hashTableDeletedValue < alignof(UniquedStringImpl));

            // Highest 8 bits are for TransitionKind; next 8 belong to TransitionPropertyAttributes.
            // Remaining bits are for UniquedStringImpl*.
            Key(UniquedStringImpl* impl, unsigned attributes, TransitionKind transitionKind)
                : m_encodedData(bitwise_cast<uintptr_t>(impl) | (static_cast<uintptr_t>(attributes) << attributesShift) | (static_cast<uintptr_t>(transitionKind) << transitionKindShift))
            {
                ASSERT(impl == this->impl());
                ASSERT(attributes <= UINT8_MAX);
                ASSERT(attributes == this->attributes());
                ASSERT(transitionKind != TransitionKind::Unknown);
                ASSERT(transitionKind == this->transitionKind());
            }

            Key() = default;

            Key(WTF::HashTableDeletedValueType)
                : m_encodedData(hashTableDeletedValue)
            { }

            bool isHashTableDeletedValue() const { return m_encodedData == hashTableDeletedValue; }

            UniquedStringImpl* impl() const { return bitwise_cast<UniquedStringImpl*>(m_encodedData & stringMask); }
            TransitionPropertyAttributes attributes() const { return (m_encodedData >> attributesShift) & UINT8_MAX; }
            TransitionKind transitionKind() const { return static_cast<TransitionKind>(m_encodedData >> transitionKindShift); }

            friend bool operator==(const Key& a, const Key& b)
            {
                return a.m_encodedData == b.m_encodedData;
            }

            friend bool operator!=(const Key& a, const Key& b)
            {
                return a.m_encodedData != b.m_encodedData;
            }

        private:
            uintptr_t m_encodedData { 0 };
        };
        using KeyTraits = SimpleClassHashTraits<Key>;

        static unsigned hash(const Key& p)
        {
            return IntHash<uintptr_t>::hash(p.m_encodedData);
        }

        static bool equal(const Key& a, const Key& b)
        {
            return a == b;
        }

        static constexpr bool safeToCompareToEmptyOrDeleted = true;
    };
#else
    struct Hash {
        using Key = std::tuple<UniquedStringImpl*, unsigned, TransitionKind>;
        using KeyTraits = HashTraits<Key>;
        
        static unsigned hash(const Key& p)
        {
            return PtrHash<UniquedStringImpl*>::hash(std::get<0>(p)) + std::get<1>(p) + static_cast<unsigned>(std::get<2>(p));
        }

        static bool equal(const Key& a, const Key& b)
        {
            return a == b;
        }

        static constexpr bool safeToCompareToEmptyOrDeleted = true;
    };
#endif

    typedef WeakGCMap<Hash::Key, Structure, Hash, Hash::KeyTraits> TransitionMap;

public:
    StructureTransitionTable()
        : m_data(UsingSingleSlotFlag)
    {
    }

    ~StructureTransitionTable()
    {
        if (!isUsingSingleSlot()) {
            delete map();
            return;
        }

        WeakImpl* impl = this->weakImpl();
        if (!impl)
            return;
        WeakSet::deallocate(impl);
    }

    void add(VM&, Structure*);
    bool contains(UniquedStringImpl*, unsigned attributes, TransitionKind) const;
    Structure* get(UniquedStringImpl*, unsigned attributes, TransitionKind) const;

private:
    friend class SingleSlotTransitionWeakOwner;

    bool isUsingSingleSlot() const
    {
        return m_data & UsingSingleSlotFlag;
    }

    TransitionMap* map() const
    {
        ASSERT(!isUsingSingleSlot());
        return bitwise_cast<TransitionMap*>(m_data);
    }

    WeakImpl* weakImpl() const
    {
        ASSERT(isUsingSingleSlot());
        return bitwise_cast<WeakImpl*>(m_data & ~UsingSingleSlotFlag);
    }

    void setMap(TransitionMap* map)
    {
        ASSERT(isUsingSingleSlot());
        
        if (WeakImpl* impl = this->weakImpl())
            WeakSet::deallocate(impl);

        // This implicitly clears the flag that indicates we're using a single transition
        m_data = bitwise_cast<intptr_t>(map);

        ASSERT(!isUsingSingleSlot());
    }

    Structure* singleTransition() const;
    void setSingleTransition(Structure*);

    intptr_t m_data;
};

} // namespace JSC
