/*
 * Copyright (C) 2015-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 "JSCast.h"
#include "VM.h"
#include "Watchpoint.h"
#include "WriteBarrier.h"
#include <wtf/Nonmovable.h>

namespace JSC {

template<typename JSCellType>
class InferredValue {
    WTF_MAKE_NONCOPYABLE(InferredValue);
    WTF_MAKE_NONMOVABLE(InferredValue);
public:
    // For the purpose of deciding whether or not to watch this variable, you only need
    // to inspect inferredValue(). If this returns something other than the empty
    // value, then it means that at all future safepoints, this watchpoint set will be
    // in one of these states:
    //
    //    IsWatched: in this case, the variable's value must still be the
    //        inferredValue.
    //
    //    IsInvalidated: in this case the variable's value may be anything but you'll
    //        either notice that it's invalidated and not install the watchpoint, or
    //        you will have been notified that the watchpoint was fired.
    JSCellType* inferredValue()
    {
        uintptr_t data = m_data;
        if (isFat(data))
            return fat(data)->inferredValue();
        return bitwise_cast<JSCellType*>(data & ValueMask);
    }

    explicit InferredValue()
        : m_data(encodeState(ClearWatchpoint))
    {
        ASSERT(inferredValue() == nullptr);
    }

    ~InferredValue()
    {
        if (isThin())
            return;
        freeFat();
    }

    // Fast way of getting the state, which only works from the main thread.
    WatchpointState stateOnJSThread() const
    {
        uintptr_t data = m_data;
        if (isFat(data))
            return fat(data)->stateOnJSThread();
        return decodeState(data);
    }

    // It is safe to call this from another thread. It may return a prior state,
    // but that should be fine since you should only perform actions based on the
    // state if you also add a watchpoint.
    WatchpointState state() const
    {
        WTF::loadLoadFence();
        uintptr_t data = m_data;
        WTF::loadLoadFence();
        if (isFat(data))
            return fat(data)->state();
        return decodeState(data);
    }

    // It is safe to call this from another thread. It may return false
    // even if the set actually had been invalidated, but that ought to happen
    // only in the case of races, and should be rare.
    bool hasBeenInvalidated() const
    {
        return state() == IsInvalidated;
    }
    
    // Like hasBeenInvalidated(), may be called from another thread.
    bool isStillValid() const
    {
        return !hasBeenInvalidated();
    }
    
    void add(Watchpoint*);
    
    void invalidate(VM& vm, const FireDetail& detail)
    {
        if (isFat())
            fat()->invalidate(vm, detail);
        else
            m_data = encodeState(IsInvalidated);
    }
    
    bool isBeingWatched() const
    {
        if (isFat())
            return fat()->isBeingWatched();
        return false;
    }

    void notifyWrite(VM& vm, JSCell* owner, JSCellType* value, const FireDetail& detail)
    {
        if (LIKELY(stateOnJSThread() == IsInvalidated))
            return;
        notifyWriteSlow(vm, owner, value, detail);
    }
    
    void notifyWrite(VM& vm, JSCell* owner, JSCellType* value, const char* reason)
    {
        if (LIKELY(stateOnJSThread() == IsInvalidated))
            return;
        notifyWriteSlow(vm, owner, value, reason);
    }
    
    void finalizeUnconditionally(VM&);

private:
    class InferredValueWatchpointSet final : public WatchpointSet {
    public:
        InferredValueWatchpointSet(WatchpointState state, JSCellType* value)
            : WatchpointSet(state)
            , m_value(value)
        {
        }

        JSCellType* inferredValue() const { return m_value; }

        void invalidate(VM& vm, const FireDetail& detail)
        {
            m_value = nullptr;
            WatchpointSet::invalidate(vm, detail);
        }

        void notifyWriteSlow(VM&, JSCell* owner, JSCellType*, const FireDetail&);

    private:
        JSCellType* m_value;
    };

    static constexpr uintptr_t IsThinFlag        = 1;
    static constexpr uintptr_t StateMask         = 6;
    static constexpr uintptr_t StateShift        = 1;
    static constexpr uintptr_t ValueMask         = ~static_cast<uintptr_t>(IsThinFlag | StateMask);
    
    static bool isThin(uintptr_t data) { return data & IsThinFlag; }
    static bool isFat(uintptr_t data) { return !isThin(data); }
    
    static WatchpointState decodeState(uintptr_t data)
    {
        ASSERT(isThin(data));
        return static_cast<WatchpointState>((data & StateMask) >> StateShift);
    }
    
    static uintptr_t encodeState(WatchpointState state)
    {
        return (static_cast<uintptr_t>(state) << StateShift) | IsThinFlag;
    }
    
    bool isThin() const { return isThin(m_data); }
    bool isFat() const { return isFat(m_data); };
    
    static InferredValueWatchpointSet* fat(uintptr_t data)
    {
        return bitwise_cast<InferredValueWatchpointSet*>(data);
    }
    
    InferredValueWatchpointSet* fat()
    {
        ASSERT(isFat());
        return fat(m_data);
    }
    
    const InferredValueWatchpointSet* fat() const
    {
        ASSERT(isFat());
        return fat(m_data);
    }
    
    InferredValueWatchpointSet* inflate()
    {
        if (LIKELY(isFat()))
            return fat();
        return inflateSlow();
    }

    InferredValueWatchpointSet* inflateSlow();
    void freeFat();

    void notifyWriteSlow(VM&, JSCell* owner, JSCellType*, const FireDetail&);
    void notifyWriteSlow(VM&, JSCell* owner, JSCellType*, const char* reason);
    
    uintptr_t m_data;
};

template<typename JSCellType>
void InferredValue<JSCellType>::InferredValueWatchpointSet::notifyWriteSlow(VM& vm, JSCell* owner, JSCellType* value, const FireDetail& detail)
{
    switch (state()) {
    case ClearWatchpoint:
        m_value = value;
        vm.heap.writeBarrier(owner, value);
        startWatching();
        return;

    case IsWatched:
        ASSERT(!!m_value);
        if (m_value == value)
            return;
        invalidate(vm, detail);
        return;

    case IsInvalidated:
        ASSERT_NOT_REACHED();
        return;
    }

    ASSERT_NOT_REACHED();
}

template<typename JSCellType>
void InferredValue<JSCellType>::notifyWriteSlow(VM& vm, JSCell* owner, JSCellType* value, const FireDetail& detail)
{
    uintptr_t data = m_data;
    if (isFat(data)) {
        fat(data)->notifyWriteSlow(vm, owner, value, detail);
        return;
    }

    switch (state()) {
    case ClearWatchpoint:
        ASSERT(decodeState(m_data) != IsInvalidated);
        m_data = (bitwise_cast<uintptr_t>(value) & ValueMask) | encodeState(IsWatched);
        vm.heap.writeBarrier(owner, value);
        return;

    case IsWatched:
        ASSERT(!!inferredValue());
        if (inferredValue() == value)
            return;
        invalidate(vm, detail);
        return;

    case IsInvalidated:
        ASSERT_NOT_REACHED();
        return;
    }

    ASSERT_NOT_REACHED();
}

template<typename JSCellType>
void InferredValue<JSCellType>::notifyWriteSlow(VM& vm, JSCell* owner, JSCellType* value, const char* reason)
{
    notifyWriteSlow(vm, owner, value, StringFireDetail(reason));
}

template<typename JSCellType>
void InferredValue<JSCellType>::add(Watchpoint* watchpoint)
{
    inflate()->add(watchpoint);
}

template<typename JSCellType>
auto InferredValue<JSCellType>::inflateSlow() -> InferredValueWatchpointSet*
{
    ASSERT(isThin());
    ASSERT(!isCompilationThread());
    uintptr_t data = m_data;
    InferredValueWatchpointSet* fat = adoptRef(new InferredValueWatchpointSet(decodeState(m_data), bitwise_cast<JSCellType*>(data & ValueMask))).leakRef();
    WTF::storeStoreFence();
    m_data = bitwise_cast<uintptr_t>(fat);
    return fat;
}

template<typename JSCellType>
void InferredValue<JSCellType>::freeFat()
{
    ASSERT(isFat());
    fat()->deref();
}

} // namespace JSC
