/*
 * Copyright (C) 2011, 2012, 2013, 2014 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. 
 */

#ifndef DFGStructureAbstractValue_h
#define DFGStructureAbstractValue_h

#if ENABLE(DFG_JIT)

#include "DFGTransition.h"
#include "JSCell.h"
#include "SpeculatedType.h"
#include "DumpContext.h"
#include "StructureSet.h"

namespace JSC { namespace DFG {

class StructureAbstractValue {
public:
    StructureAbstractValue() { }
    StructureAbstractValue(Structure* structure)
        : m_set(structure)
    {
        setClobbered(false);
    }
    StructureAbstractValue(const StructureSet& other)
        : m_set(other)
    {
        setClobbered(false);
    }
    ALWAYS_INLINE StructureAbstractValue(const StructureAbstractValue& other)
        : m_set(other.m_set)
    {
        setClobbered(other.isClobbered());
    }
    
    ALWAYS_INLINE StructureAbstractValue& operator=(const StructureAbstractValue& other)
    {
        m_set = other.m_set;
        setClobbered(other.isClobbered());
        return *this;
    }
    
    void clear()
    {
        m_set.clear();
        setClobbered(false);
    }
    
    void makeTop()
    {
        m_set.deleteStructureListIfNecessary();
        m_set.m_pointer = topValue;
    }
    
#if ASSERT_DISABLED
    void assertIsWatched(Graph&) const { }
#else
    void assertIsWatched(Graph&) const;
#endif
    
    void clobber();
    void observeInvalidationPoint() { setClobbered(false); }
    
    void observeTransition(Structure* from, Structure* to);
    void observeTransitions(const TransitionVector&);
    
    static StructureAbstractValue top()
    {
        StructureAbstractValue result;
        result.m_set.m_pointer = topValue;
        return result;
    }
    
    bool isClear() const { return m_set.isEmpty(); }
    bool isTop() const { return m_set.m_pointer == topValue; }
    bool isNeitherClearNorTop() const { return !isClear() && !isTop(); }
    
    // A clobbered abstract value means that the set currently contains the m_set set of
    // structures plus TOP, except that the "plus TOP" will go away at the next invalidation
    // point. Note that it's tempting to think of this as "the set of structures in m_set plus
    // the set of structures transition-reachable from m_set" - but this isn't really correct,
    // since if we add an unwatchable structure after clobbering, the two definitions are not
    // equivalent. If we do this, the new unwatchable structure will be added to m_set.
    // Invalidation points do not try to "clip" the set of transition-reachable structures from
    // m_set by looking at reachability as this would mean that the new set is TOP. Instead they
    // literally assume that the set is just m_set rather than m_set plus TOP.
    bool isClobbered() const { return m_set.getReservedFlag(); }
    
    bool add(Structure* structure);
    
    bool merge(const StructureSet& other);
    
    ALWAYS_INLINE bool merge(const StructureAbstractValue& other)
    {
        if (other.isClear())
            return false;
        
        if (isTop())
            return false;
        
        if (other.isTop()) {
            makeTop();
            return true;
        }
        
        return mergeSlow(other);
    }
    
    void filter(const StructureSet& other);
    void filter(const StructureAbstractValue& other);
    
    ALWAYS_INLINE void filter(SpeculatedType type)
    {
        if (!(type & SpecCell)) {
            clear();
            return;
        }
        if (isNeitherClearNorTop())
            filterSlow(type);
    }
    
    ALWAYS_INLINE bool operator==(const StructureAbstractValue& other) const
    {
        if ((m_set.isThin() && other.m_set.isThin()) || isTop() || other.isTop())
            return m_set.m_pointer == other.m_set.m_pointer;
        
        return equalsSlow(other);
    }
    
    size_t size() const
    {
        ASSERT(!isTop());
        return m_set.size();
    }
    
    Structure* at(size_t i) const
    {
        ASSERT(!isTop());
        return m_set.at(i);
    }
    
    Structure* operator[](size_t i) const { return at(i); }
    
    // FIXME: Eliminate all uses of this method. There shouldn't be any
    // special-casing for the one-structure case.
    // https://bugs.webkit.org/show_bug.cgi?id=133229
    Structure* onlyStructure() const
    {
        if (isTop() || size() != 1)
            return nullptr;
        return at(0);
    }
    
    void dumpInContext(PrintStream&, DumpContext*) const;
    void dump(PrintStream&) const;
    
    // The methods below are all conservative and err on the side of making 'this' appear bigger
    // than it is. For example, contains() may return true if the set is clobbered or TOP.
    // isSubsetOf() may return false in case of ambiguities. Therefore you should only perform
    // optimizations as a consequence of the "this is smaller" return value - so false for
    // contains(), true for isSubsetOf(), false for isSupersetOf(), and false for overlaps().

    bool contains(Structure* structure) const;
    
    bool isSubsetOf(const StructureSet& other) const;
    bool isSubsetOf(const StructureAbstractValue& other) const;
    
    bool isSupersetOf(const StructureSet& other) const;
    bool isSupersetOf(const StructureAbstractValue& other) const
    {
        return other.isSubsetOf(*this);
    }
    
    bool overlaps(const StructureSet& other) const;
    bool overlaps(const StructureAbstractValue& other) const;
    
private:
    static const uintptr_t clobberedFlag = StructureSet::reservedFlag;
    static const uintptr_t topValue = StructureSet::reservedValue;
    static const unsigned polymorphismLimit = 10;
    static const unsigned clobberedSupremacyThreshold = 2;
    
    void filterSlow(SpeculatedType type);
    bool mergeSlow(const StructureAbstractValue& other);
    
    bool equalsSlow(const StructureAbstractValue& other) const;
    
    void makeTopWhenThin()
    {
        ASSERT(m_set.isThin());
        m_set.m_pointer = topValue;
    }
    
    bool mergeNotTop(const StructureSet& other);
    
    void setClobbered(bool clobbered)
    {
        ASSERT(!isTop() || !clobbered);
        m_set.setReservedFlag(clobbered);
    }
    
    StructureSet m_set;
};

} } // namespace JSC::DFG

#endif // ENABLE(DFG_JIT)

#endif // DFGStructureAbstractValue_h


