DFGStructureAbstractValue.h [plain text]
#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 {
class TrackedReferences;
namespace DFG {
class StructureAbstractValue {
public:
StructureAbstractValue() { }
StructureAbstractValue(Structure* structure)
: m_set(StructureSet(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=(Structure* structure)
{
m_set = StructureSet(structure);
setClobbered(false);
return *this;
}
ALWAYS_INLINE StructureAbstractValue& operator=(const StructureSet& other)
{
m_set = other;
setClobbered(false);
return *this;
}
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.deleteListIfNecessary();
m_set.m_pointer = topValue;
}
#if ASSERT_DISABLED
void assertIsRegistered(Graph&) const { }
#else
void assertIsRegistered(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(); }
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);
}
const StructureSet& set() const
{
ASSERT(!isTop());
return m_set;
}
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); }
Structure* onlyStructure() const
{
if (isTop() || isClobbered())
return nullptr;
return m_set.onlyStructure();
}
void dumpInContext(PrintStream&, DumpContext*) const;
void dump(PrintStream&) const;
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;
void validateReferences(const TrackedReferences&) 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;
};
} }
#endif // ENABLE(DFG_JIT)
#endif // DFGStructureAbstractValue_h