/*
 * Copyright (C) 2012-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 "ConcurrentJSLock.h"
#include "ValueProfile.h"
#include "VirtualRegister.h"
#include <wtf/HashMap.h>
#include <wtf/Noncopyable.h>
#include <wtf/SegmentedVector.h>

namespace JSC {

class ScriptExecutable;

class LazyOperandValueProfileKey {
public:
    LazyOperandValueProfileKey()
        : m_operand(VirtualRegister()) // not a valid operand index in our current scheme
    {
    }
    
    LazyOperandValueProfileKey(WTF::HashTableDeletedValueType)
        : m_bytecodeIndex(WTF::HashTableDeletedValue)
        , m_operand(VirtualRegister()) // not a valid operand index in our current scheme
    {
    }
    
    LazyOperandValueProfileKey(BytecodeIndex bytecodeIndex, VirtualRegister operand)
        : m_bytecodeIndex(bytecodeIndex)
        , m_operand(operand)
    {
        ASSERT(m_operand.isValid());
    }
    
    bool operator!() const
    {
        return !m_operand.isValid();
    }
    
    bool operator==(const LazyOperandValueProfileKey& other) const
    {
        return m_bytecodeIndex == other.m_bytecodeIndex
            && m_operand == other.m_operand;
    }
    
    unsigned hash() const
    {
        return m_bytecodeIndex.hash() + m_operand.offset();
    }
    
    BytecodeIndex bytecodeIndex() const
    {
        ASSERT(!!*this);
        return m_bytecodeIndex;
    }

    VirtualRegister operand() const
    {
        ASSERT(!!*this);
        return m_operand;
    }
    
    bool isHashTableDeletedValue() const
    {
        return !m_operand.isValid() && m_bytecodeIndex.isHashTableDeletedValue();
    }
private: 
    BytecodeIndex m_bytecodeIndex;
    VirtualRegister m_operand;
};

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

} // namespace JSC

namespace WTF {

template<typename T> struct DefaultHash;
template<> struct DefaultHash<JSC::LazyOperandValueProfileKey> {
    typedef JSC::LazyOperandValueProfileKeyHash Hash;
};

template<typename T> struct HashTraits;
template<> struct HashTraits<JSC::LazyOperandValueProfileKey> : public GenericHashTraits<JSC::LazyOperandValueProfileKey> {
    static void constructDeletedValue(JSC::LazyOperandValueProfileKey& slot) { new (NotNull, &slot) JSC::LazyOperandValueProfileKey(HashTableDeletedValue); }
    static bool isDeletedValue(const JSC::LazyOperandValueProfileKey& value) { return value.isHashTableDeletedValue(); }
};

} // namespace WTF

namespace JSC {

struct LazyOperandValueProfile : public MinimalValueProfile {
    LazyOperandValueProfile()
        : MinimalValueProfile()
        , m_operand(VirtualRegister())
    {
    }
    
    explicit LazyOperandValueProfile(const LazyOperandValueProfileKey& key)
        : MinimalValueProfile()
        , m_key(key)
    {
    }
    
    LazyOperandValueProfileKey key() const
    {
        return m_key;
    }
    
    VirtualRegister m_operand;
    LazyOperandValueProfileKey m_key;
    
    typedef SegmentedVector<LazyOperandValueProfile, 8> List;
};

class LazyOperandValueProfileParser;

class CompressedLazyOperandValueProfileHolder {
    WTF_MAKE_NONCOPYABLE(CompressedLazyOperandValueProfileHolder);
public:
    CompressedLazyOperandValueProfileHolder();
    ~CompressedLazyOperandValueProfileHolder();
    
    void computeUpdatedPredictions(const ConcurrentJSLocker&);
    
    LazyOperandValueProfile* add(
        const ConcurrentJSLocker&, const LazyOperandValueProfileKey& key);
    
private:
    friend class LazyOperandValueProfileParser;
    std::unique_ptr<LazyOperandValueProfile::List> m_data;
};

class LazyOperandValueProfileParser {
    WTF_MAKE_NONCOPYABLE(LazyOperandValueProfileParser);
public:
    explicit LazyOperandValueProfileParser();
    ~LazyOperandValueProfileParser();
    
    void initialize(
        const ConcurrentJSLocker&, CompressedLazyOperandValueProfileHolder& holder);
    
    LazyOperandValueProfile* getIfPresent(
        const LazyOperandValueProfileKey& key) const;
    
    SpeculatedType prediction(
        const ConcurrentJSLocker&, const LazyOperandValueProfileKey& key) const;
private:
    HashMap<LazyOperandValueProfileKey, LazyOperandValueProfile*> m_map;
};

} // namespace JSC
