/*
 * Copyright (C) 2017-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/HashTable.h>

namespace JSC {

class FunctionExecutable;
class JSGlobalObject;
class JSObject;

class PrototypeKey {
public:
    PrototypeKey() { }
    
    PrototypeKey(JSObject* prototype, FunctionExecutable* executable, unsigned inlineCapacity, const ClassInfo* classInfo, JSGlobalObject* globalObject)
        : m_prototype(prototype)
        , m_executable(executable)
        , m_inlineCapacity(inlineCapacity)
        , m_classInfo(classInfo)
        , m_globalObject(globalObject)
    {
    }
    
    PrototypeKey(WTF::HashTableDeletedValueType)
        : m_inlineCapacity(1)
    {
    }
    
    JSObject* prototype() const { return m_prototype; }
    FunctionExecutable* executable() const { return m_executable; }
    unsigned inlineCapacity() const { return m_inlineCapacity; }
    const ClassInfo* classInfo() const { return m_classInfo; }
    JSGlobalObject* globalObject() const { return m_globalObject; }
    
    bool operator==(const PrototypeKey& other) const
    {
        return m_prototype == other.m_prototype
            && m_executable == other.m_executable
            && m_inlineCapacity == other.m_inlineCapacity
            && m_classInfo == other.m_classInfo
            && m_globalObject == other.m_globalObject;
    }
    
    bool operator!=(const PrototypeKey& other) const { return !(*this == other); }
    explicit operator bool() const { return *this != PrototypeKey(); }
    bool isHashTableDeletedValue() const { return *this == PrototypeKey(WTF::HashTableDeletedValue); }
    
    unsigned hash() const
    {
        return WTF::IntHash<uintptr_t>::hash(bitwise_cast<uintptr_t>(m_prototype) ^ bitwise_cast<uintptr_t>(m_executable) ^ bitwise_cast<uintptr_t>(m_classInfo) ^ bitwise_cast<uintptr_t>(m_globalObject)) + m_inlineCapacity;
    }
    
private:
    // WARNING: We require all of these default values to be zero. Otherwise, you'll need to add
    // "static constexpr bool emptyValueIsZero = false;" to the HashTraits at the bottom of this file.
    JSObject* m_prototype { nullptr }; 
    FunctionExecutable* m_executable { nullptr }; 
    unsigned m_inlineCapacity { 0 };
    const ClassInfo* m_classInfo { nullptr };
    JSGlobalObject* m_globalObject { nullptr };
};

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

} // namespace JSC

namespace WTF {

template<typename T> struct DefaultHash;
template<> struct DefaultHash<JSC::PrototypeKey> {
    typedef JSC::PrototypeKeyHash Hash;
};

template<typename T> struct HashTraits;
template<> struct HashTraits<JSC::PrototypeKey> : SimpleClassHashTraits<JSC::PrototypeKey> { };

} // namespace WTF

