/*
 * Copyright (C) 2015-2016 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 "JSObject.h"
#include <wtf/HashMap.h>

namespace JSC {

class TrackedReferences;

class PropertyCondition {
public:
    enum Kind {
        Presence,
        Absence,
        AbsenceOfSetter,
        Equivalence // An adaptive watchpoint on this will be a pair of watchpoints, and when the structure transitions, we will set the replacement watchpoint on the new structure.
    };
    
    PropertyCondition()
        : m_uid(nullptr)
        , m_kind(Presence)
    {
        memset(&u, 0, sizeof(u));
    }
    
    PropertyCondition(WTF::HashTableDeletedValueType)
        : m_uid(nullptr)
        , m_kind(Absence)
    {
        memset(&u, 0, sizeof(u));
    }
    
    static PropertyCondition presenceWithoutBarrier(UniquedStringImpl* uid, PropertyOffset offset, unsigned attributes)
    {
        PropertyCondition result;
        result.m_uid = uid;
        result.m_kind = Presence;
        result.u.presence.offset = offset;
        result.u.presence.attributes = attributes;
        return result;
    }
    
    static PropertyCondition presence(
        VM&, JSCell*, UniquedStringImpl* uid, PropertyOffset offset, unsigned attributes)
    {
        return presenceWithoutBarrier(uid, offset, attributes);
    }

    // NOTE: The prototype is the storedPrototype not the prototypeForLookup.
    static PropertyCondition absenceWithoutBarrier(UniquedStringImpl* uid, JSObject* prototype)
    {
        PropertyCondition result;
        result.m_uid = uid;
        result.m_kind = Absence;
        result.u.absence.prototype = prototype;
        return result;
    }
    
    static PropertyCondition absence(
        VM& vm, JSCell* owner, UniquedStringImpl* uid, JSObject* prototype)
    {
        if (owner)
            vm.heap.writeBarrier(owner);
        return absenceWithoutBarrier(uid, prototype);
    }
    
    static PropertyCondition absenceOfSetterWithoutBarrier(
        UniquedStringImpl* uid, JSObject* prototype)
    {
        PropertyCondition result;
        result.m_uid = uid;
        result.m_kind = AbsenceOfSetter;
        result.u.absence.prototype = prototype;
        return result;
    }
    
    static PropertyCondition absenceOfSetter(
        VM& vm, JSCell* owner, UniquedStringImpl* uid, JSObject* prototype)
    {
        if (owner)
            vm.heap.writeBarrier(owner);
        return absenceOfSetterWithoutBarrier(uid, prototype);
    }
    
    static PropertyCondition equivalenceWithoutBarrier(
        UniquedStringImpl* uid, JSValue value)
    {
        PropertyCondition result;
        result.m_uid = uid;
        result.m_kind = Equivalence;
        result.u.equivalence.value = JSValue::encode(value);
        return result;
    }
        
    static PropertyCondition equivalence(
        VM& vm, JSCell* owner, UniquedStringImpl* uid, JSValue value)
    {
        if (value.isCell() && owner)
            vm.heap.writeBarrier(owner);
        return equivalenceWithoutBarrier(uid, value);
    }
    
    explicit operator bool() const { return m_uid || m_kind != Presence; }
    
    Kind kind() const { return m_kind; }
    UniquedStringImpl* uid() const { return m_uid; }
    
    bool hasOffset() const { return !!*this && m_kind == Presence; };
    PropertyOffset offset() const
    {
        ASSERT(hasOffset());
        return u.presence.offset;
    }
    bool hasAttributes() const { return !!*this && m_kind == Presence; };
    unsigned attributes() const
    {
        ASSERT(hasAttributes());
        return u.presence.attributes;
    }
    
    bool hasPrototype() const { return !!*this && (m_kind == Absence || m_kind == AbsenceOfSetter); }
    JSObject* prototype() const
    {
        ASSERT(hasPrototype());
        return u.absence.prototype;
    }
    
    bool hasRequiredValue() const { return !!*this && m_kind == Equivalence; }
    JSValue requiredValue() const
    {
        ASSERT(hasRequiredValue());
        return JSValue::decode(u.equivalence.value);
    }
    
    void dumpInContext(PrintStream&, DumpContext*) const;
    void dump(PrintStream&) const;
    
    unsigned hash() const
    {
        unsigned result = WTF::PtrHash<UniquedStringImpl*>::hash(m_uid) + static_cast<unsigned>(m_kind);
        switch (m_kind) {
        case Presence:
            result ^= u.presence.offset;
            result ^= u.presence.attributes;
            break;
        case Absence:
        case AbsenceOfSetter:
            result ^= WTF::PtrHash<JSObject*>::hash(u.absence.prototype);
            break;
        case Equivalence:
            result ^= EncodedJSValueHash::hash(u.equivalence.value);
            break;
        }
        return result;
    }
    
    bool operator==(const PropertyCondition& other) const
    {
        if (m_uid != other.m_uid)
            return false;
        if (m_kind != other.m_kind)
            return false;
        switch (m_kind) {
        case Presence:
            return u.presence.offset == other.u.presence.offset
                && u.presence.attributes == other.u.presence.attributes;
        case Absence:
        case AbsenceOfSetter:
            return u.absence.prototype == other.u.absence.prototype;
        case Equivalence:
            return u.equivalence.value == other.u.equivalence.value;
        }
        RELEASE_ASSERT_NOT_REACHED();
        return false;
    }
    
    bool isHashTableDeletedValue() const
    {
        return !m_uid && m_kind == Absence;
    }
    
    // Two conditions are compatible if they are identical or if they speak of different uids. If
    // false is returned, you have to decide how to resolve the conflict - for example if there is
    // a Presence and an Equivalence then in some cases you'll want the more general of the two
    // while in other cases you'll want the more specific of the two. This will also return false
    // for contradictions, like Presence and Absence on the same uid. By convention, invalid
    // conditions aren't compatible with anything.
    bool isCompatibleWith(const PropertyCondition& other) const
    {
        if (!*this || !other)
            return false;
        return *this == other || uid() != other.uid();
    }
    
    // Checks if the object's structure claims that the property won't be intercepted.
    bool isStillValidAssumingImpurePropertyWatchpoint(Structure*, JSObject* base = nullptr) const;
    
    // Returns true if we need an impure property watchpoint to ensure validity even if
    // isStillValidAccordingToStructure() returned true.
    bool validityRequiresImpurePropertyWatchpoint(Structure*) const;
    
    // Checks if the condition is still valid right now for the given object and structure.
    // May conservatively return false, if the object and structure alone don't guarantee the
    // condition. This happens for an Absence condition on an object that may have impure
    // properties. If the object is not supplied, then a "true" return indicates that checking if
    // an object has the given structure guarantees the condition still holds. If an object is
    // supplied, then you may need to use some other watchpoints on the object to guarantee the
    // condition in addition to the structure check.
    bool isStillValid(Structure*, JSObject* base = nullptr) const;
    
    // In some cases, the condition is not watchable, but could be made watchable by enabling the
    // appropriate watchpoint. For example, replacement watchpoints are enabled only when some
    // access is cached on the property in some structure. This is mainly to save space for
    // dictionary properties or properties that never get very hot. But, it's always safe to
    // enable watching, provided that this is called from the main thread.
    enum WatchabilityEffort {
        // This is the default. It means that we don't change the state of any Structure or
        // object, and implies that if the property happens not to be watchable then we don't make
        // it watchable. This is mandatory if calling from a JIT thread. This is also somewhat
        // preferable when first deciding whether to watch a condition for the first time (i.e.
        // not from a watchpoint fire that causes us to see if we should adapt), since a
        // watchpoint not being initialized for watching implies that maybe we don't know enough
        // yet to make it profitable to watch -- as in, the thing being watched may not have
        // stabilized yet. We prefer to only assume that a condition will hold if it has been
        // known to hold for a while already.
        MakeNoChanges,
        
        // Do what it takes to ensure that the property can be watched, if doing so has no
        // user-observable effect. For now this just means that we will ensure that a property
        // replacement watchpoint is enabled if it hadn't been enabled already. Do not use this
        // from JIT threads, since the act of enabling watchpoints is not thread-safe.
        EnsureWatchability
    };
    
    // This means that it's still valid and we could enforce validity by setting a transition
    // watchpoint on the structure and possibly an impure property watchpoint.
    bool isWatchableAssumingImpurePropertyWatchpoint(
        Structure*, JSObject* base = nullptr, WatchabilityEffort = MakeNoChanges) const;
    
    // This means that it's still valid and we could enforce validity by setting a transition
    // watchpoint on the structure.
    bool isWatchable(
        Structure*, JSObject* base = nullptr, WatchabilityEffort = MakeNoChanges) const;
    
    bool watchingRequiresStructureTransitionWatchpoint() const
    {
        // Currently, this is required for all of our conditions.
        return !!*this;
    }
    bool watchingRequiresReplacementWatchpoint() const
    {
        return !!*this && m_kind == Equivalence;
    }
    
    // This means that the objects involved in this are still live.
    bool isStillLive() const;
    
    void validateReferences(const TrackedReferences&) const;

    static bool isValidValueForAttributes(VM&, JSValue, unsigned attributes);

    bool isValidValueForPresence(VM&, JSValue) const;

    PropertyCondition attemptToMakeEquivalenceWithoutBarrier(VM&, JSObject* base) const;

private:
    bool isWatchableWhenValid(Structure*, WatchabilityEffort) const;

    UniquedStringImpl* m_uid;
    Kind m_kind;
    union {
        struct {
            PropertyOffset offset;
            unsigned attributes;
        } presence;
        struct {
            JSObject* prototype;
        } absence;
        struct {
            EncodedJSValue value;
        } equivalence;
    } u;
};

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

} // namespace JSC

namespace WTF {

void printInternal(PrintStream&, JSC::PropertyCondition::Kind);

template<typename T> struct DefaultHash;
template<> struct DefaultHash<JSC::PropertyCondition> {
    typedef JSC::PropertyConditionHash Hash;
};

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

} // namespace WTF
