diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
commit | 32761a6cee1d0dee366b885b7b9c777e67885688 (patch) | |
tree | d6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h | |
parent | a4e969f4965059196ca948db781e52f7cfebf19e (diff) | |
download | WebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz |
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h | 376 |
1 files changed, 224 insertions, 152 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h b/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h index a1a5f2982..54d3bd29b 100644 --- a/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h +++ b/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2015 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,241 +26,313 @@ #ifndef DFGStructureAbstractValue_h #define DFGStructureAbstractValue_h +#include <wtf/Platform.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 { +namespace JSC { namespace DFG { class StructureAbstractValue { public: - StructureAbstractValue() { } - StructureAbstractValue(Structure* structure) - : m_set(StructureSet(structure)) + StructureAbstractValue() + : m_structure(0) { - setClobbered(false); } - StructureAbstractValue(const StructureSet& other) - : m_set(other) + + StructureAbstractValue(Structure* structure) + : m_structure(structure) { - setClobbered(false); } - ALWAYS_INLINE StructureAbstractValue(const StructureAbstractValue& other) - : m_set(other.m_set) + + StructureAbstractValue(const StructureSet& set) { - setClobbered(other.isClobbered()); + switch (set.size()) { + case 0: + m_structure = 0; + break; + + case 1: + m_structure = set[0]; + break; + + default: + m_structure = topValue(); + break; + } } - ALWAYS_INLINE StructureAbstractValue& operator=(Structure* structure) + void clear() { - m_set = StructureSet(structure); - setClobbered(false); - return *this; + m_structure = 0; } - ALWAYS_INLINE StructureAbstractValue& operator=(const StructureSet& other) + + void makeTop() { - m_set = other; - setClobbered(false); - return *this; + m_structure = topValue(); } - ALWAYS_INLINE StructureAbstractValue& operator=(const StructureAbstractValue& other) + + static StructureAbstractValue top() { - m_set = other.m_set; - setClobbered(other.isClobbered()); - return *this; + StructureAbstractValue value; + value.makeTop(); + return value; } - void clear() + void add(Structure* structure) { - m_set.clear(); - setClobbered(false); + ASSERT(!contains(structure) && !isTop()); + if (m_structure) + makeTop(); + else + m_structure = structure; } - void makeTop() + bool addAll(const StructureSet& other) { - m_set.deleteListIfNecessary(); - m_set.m_pointer = topValue; + if (isTop() || !other.size()) + return false; + if (other.size() > 1) { + makeTop(); + return true; + } + if (!m_structure) { + m_structure = other[0]; + return true; + } + if (m_structure == other[0]) + return false; + makeTop(); + return true; } -#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() + bool addAll(const StructureAbstractValue& other) { - StructureAbstractValue result; - result.m_set.m_pointer = topValue; - return result; + if (!other.m_structure) + return false; + if (isTop()) + return false; + if (other.isTop()) { + makeTop(); + return true; + } + if (m_structure) { + if (m_structure == other.m_structure) + return false; + makeTop(); + return true; + } + m_structure = other.m_structure; + return true; } - 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(); } - - // A finite structure abstract value is one where enumerating over it will yield all - // of the structures that the value may have right now. This is true so long as we're - // neither top nor clobbered. - bool isFinite() const { return !isTop() && !isClobbered(); } - - // An infinite structure abstract value may currently have any structure. - bool isInfinite() const { return !isFinite(); } + bool contains(Structure* structure) const + { + if (isTop()) + return true; + if (m_structure == structure) + return true; + return false; + } - bool add(Structure* structure); + bool isSubsetOf(const StructureSet& other) const + { + if (isTop()) + return false; + if (!m_structure) + return true; + return other.contains(m_structure); + } - bool merge(const StructureSet& other); + bool doesNotContainAnyOtherThan(Structure* structure) const + { + if (isTop()) + return false; + if (!m_structure) + return true; + return m_structure == structure; + } - ALWAYS_INLINE bool merge(const StructureAbstractValue& other) + bool isSupersetOf(const StructureSet& other) const { - if (other.isClear()) + if (isTop()) + return true; + if (!other.size()) + return true; + if (other.size() > 1) return false; - + return m_structure == other[0]; + } + + bool isSubsetOf(const StructureAbstractValue& other) const + { + if (other.isTop()) + return true; if (isTop()) return false; + if (m_structure) { + if (other.m_structure) + return m_structure == other.m_structure; + return false; + } + return true; + } + + bool isSupersetOf(const StructureAbstractValue& other) const + { + return other.isSubsetOf(*this); + } + + void filter(const StructureSet& other) + { + if (!m_structure) + return; - if (other.isTop()) { - makeTop(); - return true; + if (isTop()) { + switch (other.size()) { + case 0: + m_structure = 0; + return; + + case 1: + m_structure = other[0]; + return; + + default: + return; + } } - return mergeSlow(other); + if (other.contains(m_structure)) + return; + + m_structure = 0; } - void filter(const StructureSet& other); - void filter(const StructureAbstractValue& other); - - ALWAYS_INLINE void filter(SpeculatedType type) + void filter(const StructureAbstractValue& other) { - if (!(type & SpecCell)) { - clear(); + if (isTop()) { + m_structure = other.m_structure; return; } - if (isNeitherClearNorTop()) - filterSlow(type); + if (m_structure == other.m_structure) + return; + if (other.isTop()) + return; + m_structure = 0; } - ALWAYS_INLINE bool operator==(const StructureAbstractValue& other) const + void filter(SpeculatedType other) { - if ((m_set.isThin() && other.m_set.isThin()) || isTop() || other.isTop()) - return m_set.m_pointer == other.m_set.m_pointer; + if (!(other & SpecCell)) { + clear(); + return; + } - return equalsSlow(other); + if (isClearOrTop()) + return; + + if (!(speculationFromStructure(m_structure) & other)) + m_structure = 0; } - const StructureSet& set() const + bool isClear() const { - ASSERT(!isTop()); - return m_set; + return !m_structure; } + bool isTop() const { return m_structure == topValue(); } + + bool isClearOrTop() const { return m_structure <= topValue(); } + bool isNeitherClearNorTop() const { return !isClearOrTop(); } + size_t size() const { ASSERT(!isTop()); - return m_set.size(); + return !!m_structure; } Structure* at(size_t i) const { ASSERT(!isTop()); - return m_set.at(i); + ASSERT(m_structure); + ASSERT_UNUSED(i, !i); + return m_structure; } - Structure* operator[](size_t i) const { return at(i); } - - // In most cases, what you really want to do is verify whether the set is top or clobbered, and - // if not, enumerate the set of structures. Use this only in cases where the singleton case is - // meaningfully special, like for transitions. - Structure* onlyStructure() const + Structure* operator[](size_t i) const { - if (isInfinite()) - return nullptr; - return m_set.onlyStructure(); + return at(i); } - - template<typename Functor> - void forEach(const Functor& functor) const + + Structure* last() const { - ASSERT(!isTop()); - m_set.forEach(functor); + 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 + SpeculatedType speculationFromStructures() const { - return other.isSubsetOf(*this); + if (isTop()) + return SpecCell; + if (isClear()) + return SpecNone; + return speculationFromStructure(m_structure); } - 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 isValidOffset(PropertyOffset offset) + { + if (isTop()) + return false; + if (isClear()) + return true; + return m_structure->isValidOffset(offset); + } - bool equalsSlow(const StructureAbstractValue& other) const; + bool hasSingleton() const + { + return isNeitherClearNorTop(); + } - void makeTopWhenThin() + Structure* singleton() const { - ASSERT(m_set.isThin()); - m_set.m_pointer = topValue; + ASSERT(isNeitherClearNorTop()); + return m_structure; } - bool mergeNotTop(const StructureSet& other); + bool operator==(const StructureAbstractValue& other) const + { + return m_structure == other.m_structure; + } - void setClobbered(bool clobbered) + void dumpInContext(PrintStream& out, DumpContext* context) const { - ASSERT(!isTop() || !clobbered); - m_set.setReservedFlag(clobbered); + if (isTop()) { + out.print("TOP"); + return; + } + + out.print("["); + if (m_structure) + out.print(inContext(*m_structure, context)); + out.print("]"); + } + + void dump(PrintStream& out) const + { + dumpInContext(out, 0); } + +private: + static Structure* topValue() { return reinterpret_cast<Structure*>(1); } + + // NB. This must have a trivial destructor. - StructureSet m_set; + // This can only remember one structure at a time. + Structure* m_structure; }; } } // namespace JSC::DFG |