/*
 * 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 "JSObject.h"
#include "PropertyCondition.h"
#include <wtf/HashMap.h>

namespace JSC {

class TrackedReferences;

class ObjectPropertyCondition {
public:
    ObjectPropertyCondition()
        : m_object(nullptr)
    {
    }
    
    ObjectPropertyCondition(WTF::HashTableDeletedValueType token)
        : m_object(nullptr)
        , m_condition(token)
    {
    }
    
    ObjectPropertyCondition(JSObject* object, const PropertyCondition& condition)
        : m_object(object)
        , m_condition(condition)
    {
    }
    
    static ObjectPropertyCondition presenceWithoutBarrier(
        JSObject* object, UniquedStringImpl* uid, PropertyOffset offset, unsigned attributes)
    {
        ObjectPropertyCondition result;
        result.m_object = object;
        result.m_condition = PropertyCondition::presenceWithoutBarrier(uid, offset, attributes); 
        return result;
    }
    
    static ObjectPropertyCondition presence(
        VM& vm, JSCell* owner, JSObject* object, UniquedStringImpl* uid, PropertyOffset offset,
        unsigned attributes)
    {
        if (owner)
            vm.heap.writeBarrier(owner);
        return presenceWithoutBarrier(object, uid, offset, attributes);
    }

    // NOTE: The prototype is the storedPrototype, not the prototypeForLookup.
    static ObjectPropertyCondition absenceWithoutBarrier(
        JSObject* object, UniquedStringImpl* uid, JSObject* prototype)
    {
        ObjectPropertyCondition result;
        result.m_object = object;
        result.m_condition = PropertyCondition::absenceWithoutBarrier(uid, prototype);
        return result;
    }
    
    static ObjectPropertyCondition absence(
        VM& vm, JSCell* owner, JSObject* object, UniquedStringImpl* uid, JSObject* prototype)
    {
        if (owner)
            vm.heap.writeBarrier(owner);
        return absenceWithoutBarrier(object, uid, prototype);
    }
    
    static ObjectPropertyCondition absenceOfSetEffectWithoutBarrier(
        JSObject* object, UniquedStringImpl* uid, JSObject* prototype)
    {
        ObjectPropertyCondition result;
        result.m_object = object;
        result.m_condition = PropertyCondition::absenceOfSetEffectWithoutBarrier(uid, prototype);
        return result;
    }
    
    static ObjectPropertyCondition absenceOfSetEffect(
        VM& vm, JSCell* owner, JSObject* object, UniquedStringImpl* uid, JSObject* prototype)
    {
        if (owner)
            vm.heap.writeBarrier(owner);
        return absenceOfSetEffectWithoutBarrier(object, uid, prototype);
    }
    
    static ObjectPropertyCondition equivalenceWithoutBarrier(
        JSObject* object, UniquedStringImpl* uid, JSValue value)
    {
        ObjectPropertyCondition result;
        result.m_object = object;
        result.m_condition = PropertyCondition::equivalenceWithoutBarrier(uid, value);
        return result;
    }
    
    static ObjectPropertyCondition equivalence(
        VM& vm, JSCell* owner, JSObject* object, UniquedStringImpl* uid, JSValue value)
    {
        if (owner)
            vm.heap.writeBarrier(owner);
        return equivalenceWithoutBarrier(object, uid, value);
    }

    static ObjectPropertyCondition customFunctionEquivalence(
        VM& vm, JSCell* owner, JSObject* object, UniquedStringImpl* uid)
    {
        ObjectPropertyCondition result;
        result.m_object = object;
        result.m_condition = PropertyCondition::customFunctionEquivalence(uid);
        if (owner)
            vm.heap.writeBarrier(owner);
        return result;
    }
    
    static ObjectPropertyCondition hasPrototypeWithoutBarrier(JSObject* object, JSObject* prototype)
    {
        ObjectPropertyCondition result;
        result.m_object = object;
        result.m_condition = PropertyCondition::hasPrototypeWithoutBarrier(prototype);
        return result;
    }
    
    static ObjectPropertyCondition hasPrototype(
        VM& vm, JSCell* owner, JSObject* object, JSObject* prototype)
    {
        if (owner)
            vm.heap.writeBarrier(owner);
        return hasPrototypeWithoutBarrier(object, prototype);
    }

    explicit operator bool() const { return !!m_condition; }
    
    JSObject* object() const { return m_object; }
    PropertyCondition condition() const { return m_condition; }
    
    PropertyCondition::Kind kind() const { return condition().kind(); }
    UniquedStringImpl* uid() const { return condition().uid(); }
    bool hasOffset() const { return condition().hasOffset(); }
    PropertyOffset offset() const { return condition().offset(); }
    unsigned hasAttributes() const { return condition().hasAttributes(); }
    unsigned attributes() const { return condition().attributes(); }
    bool hasPrototype() const { return condition().hasPrototype(); }
    JSObject* prototype() const { return condition().prototype(); }
    bool hasRequiredValue() const { return condition().hasRequiredValue(); }
    JSValue requiredValue() const { return condition().requiredValue(); }
    
    void dumpInContext(PrintStream&, DumpContext*) const;
    void dump(PrintStream&) const;
    
    unsigned hash() const
    {
        return WTF::PtrHash<JSObject*>::hash(m_object) ^ m_condition.hash();
    }
    
    bool operator==(const ObjectPropertyCondition& other) const
    {
        return m_object == other.m_object
            && m_condition == other.m_condition;
    }
    
    bool isHashTableDeletedValue() const
    {
        return !m_object && m_condition.isHashTableDeletedValue();
    }
    
    // Two conditions are compatible if they are identical or if they speak of different uids or
    // different objects. 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
    // object/uid. By convention, invalid conditions aren't compatible with anything.
    bool isCompatibleWith(const ObjectPropertyCondition& other) const
    {
        if (!*this || !other)
            return false;
        return *this == other || uid() != other.uid() || object() != other.object();
    }
    
    // These validity-checking methods can optionally take a Struture* instead of loading the
    // Structure* from the object. If you're in the concurrent JIT, then you must use the forms
    // that take an explicit Structure* because you want the compiler to optimize for the same
    // structure that you validated (i.e. avoid a TOCTOU race).
    
    // Checks if the object's structure claims that the property won't be intercepted. Validity
    // does not require watchpoints on the object.
    bool structureEnsuresValidityAssumingImpurePropertyWatchpoint() const;
    
    // Returns true if we need an impure property watchpoint to ensure validity even if
    // isStillValidAccordingToStructure() returned true.
    bool validityRequiresImpurePropertyWatchpoint(Structure*) const;
    bool validityRequiresImpurePropertyWatchpoint() const;

    // Checks if the condition still holds setting aside the need for an impure property watchpoint.
    // Validity might still require watchpoints on the object.
    bool isStillValidAssumingImpurePropertyWatchpoint(Structure*) const;
    bool isStillValidAssumingImpurePropertyWatchpoint() const;

    // Checks if the condition still holds. May conservatively return false, if the object and
    // structure alone don't guarantee the condition. Note that this may return true if the
    // condition still requires some watchpoints on the object in addition to checking the
    // structure. If you want to check if the condition holds by using the structure alone,
    // use structureEnsuresValidity().
    bool isStillValid(Structure*) const;
    bool isStillValid() const;
    
    // Shorthand for condition().isStillValid(structure).
    bool structureEnsuresValidity(Structure*) const;
    bool structureEnsuresValidity() const;
    
    // 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*,
        PropertyCondition::WatchabilityEffort = PropertyCondition::MakeNoChanges) const;
    bool isWatchableAssumingImpurePropertyWatchpoint(
        PropertyCondition::WatchabilityEffort = PropertyCondition::MakeNoChanges) const;

    // This means that it's still valid and we could enforce validity by setting a transition
    // watchpoint on the structure, and a value change watchpoint if we're Equivalence.
    bool isWatchable(
        Structure*,
        PropertyCondition::WatchabilityEffort = PropertyCondition::MakeNoChanges) const;
    bool isWatchable(
        PropertyCondition::WatchabilityEffort = PropertyCondition::MakeNoChanges) const;
    
    bool watchingRequiresStructureTransitionWatchpoint() const
    {
        return condition().watchingRequiresStructureTransitionWatchpoint();
    }
    bool watchingRequiresReplacementWatchpoint() const
    {
        return condition().watchingRequiresReplacementWatchpoint();
    }

    template<typename Functor>
    void forEachDependentCell(const Functor& functor) const
    {
        functor(m_object);
        m_condition.forEachDependentCell(functor);
    }
    
    // This means that the objects involved in this are still live.
    bool isStillLive(VM&) const;
    
    void validateReferences(const TrackedReferences&) const;

    bool isValidValueForPresence(VM& vm, JSValue value) const
    {
        return condition().isValidValueForPresence(vm, value);
    }

    ObjectPropertyCondition attemptToMakeEquivalenceWithoutBarrier(VM&) const;

private:
    JSObject* m_object;
    PropertyCondition m_condition;
};

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

} // namespace JSC

namespace WTF {

template<typename T> struct DefaultHash;
template<> struct DefaultHash<JSC::ObjectPropertyCondition> {
    typedef JSC::ObjectPropertyConditionHash Hash;
};

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

} // namespace WTF
