2 * Copyright (C) 2011-2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef DFGStructureAbstractValue_h
27 #define DFGStructureAbstractValue_h
31 #include "DFGTransition.h"
33 #include "SpeculatedType.h"
34 #include "DumpContext.h"
35 #include "StructureSet.h"
39 class TrackedReferences
;
43 class StructureAbstractValue
{
45 StructureAbstractValue() { }
46 StructureAbstractValue(Structure
* structure
)
47 : m_set(StructureSet(structure
))
51 StructureAbstractValue(const StructureSet
& other
)
56 ALWAYS_INLINE
StructureAbstractValue(const StructureAbstractValue
& other
)
59 setClobbered(other
.isClobbered());
62 ALWAYS_INLINE StructureAbstractValue
& operator=(Structure
* structure
)
64 m_set
= StructureSet(structure
);
68 ALWAYS_INLINE StructureAbstractValue
& operator=(const StructureSet
& other
)
74 ALWAYS_INLINE StructureAbstractValue
& operator=(const StructureAbstractValue
& other
)
77 setClobbered(other
.isClobbered());
89 m_set
.deleteListIfNecessary();
90 m_set
.m_pointer
= topValue
;
94 void assertIsRegistered(Graph
&) const { }
96 void assertIsRegistered(Graph
&) const;
100 void observeInvalidationPoint() { setClobbered(false); }
102 void observeTransition(Structure
* from
, Structure
* to
);
103 void observeTransitions(const TransitionVector
&);
105 static StructureAbstractValue
top()
107 StructureAbstractValue result
;
108 result
.m_set
.m_pointer
= topValue
;
112 bool isClear() const { return m_set
.isEmpty(); }
113 bool isTop() const { return m_set
.m_pointer
== topValue
; }
114 bool isNeitherClearNorTop() const { return !isClear() && !isTop(); }
116 // A clobbered abstract value means that the set currently contains the m_set set of
117 // structures plus TOP, except that the "plus TOP" will go away at the next invalidation
118 // point. Note that it's tempting to think of this as "the set of structures in m_set plus
119 // the set of structures transition-reachable from m_set" - but this isn't really correct,
120 // since if we add an unwatchable structure after clobbering, the two definitions are not
121 // equivalent. If we do this, the new unwatchable structure will be added to m_set.
122 // Invalidation points do not try to "clip" the set of transition-reachable structures from
123 // m_set by looking at reachability as this would mean that the new set is TOP. Instead they
124 // literally assume that the set is just m_set rather than m_set plus TOP.
125 bool isClobbered() const { return m_set
.getReservedFlag(); }
127 bool add(Structure
* structure
);
129 bool merge(const StructureSet
& other
);
131 ALWAYS_INLINE
bool merge(const StructureAbstractValue
& other
)
144 return mergeSlow(other
);
147 void filter(const StructureSet
& other
);
148 void filter(const StructureAbstractValue
& other
);
150 ALWAYS_INLINE
void filter(SpeculatedType type
)
152 if (!(type
& SpecCell
)) {
156 if (isNeitherClearNorTop())
160 ALWAYS_INLINE
bool operator==(const StructureAbstractValue
& other
) const
162 if ((m_set
.isThin() && other
.m_set
.isThin()) || isTop() || other
.isTop())
163 return m_set
.m_pointer
== other
.m_set
.m_pointer
;
165 return equalsSlow(other
);
168 const StructureSet
& set() const
180 Structure
* at(size_t i
) const
186 Structure
* operator[](size_t i
) const { return at(i
); }
188 // In most cases, what you really want to do is verify whether the set is top or clobbered, and
189 // if not, enumerate the set of structures. Use this only in cases where the singleton case is
190 // meaningfully special, like for transitions.
191 Structure
* onlyStructure() const
193 if (isTop() || isClobbered())
195 return m_set
.onlyStructure();
198 void dumpInContext(PrintStream
&, DumpContext
*) const;
199 void dump(PrintStream
&) const;
201 // The methods below are all conservative and err on the side of making 'this' appear bigger
202 // than it is. For example, contains() may return true if the set is clobbered or TOP.
203 // isSubsetOf() may return false in case of ambiguities. Therefore you should only perform
204 // optimizations as a consequence of the "this is smaller" return value - so false for
205 // contains(), true for isSubsetOf(), false for isSupersetOf(), and false for overlaps().
207 bool contains(Structure
* structure
) const;
209 bool isSubsetOf(const StructureSet
& other
) const;
210 bool isSubsetOf(const StructureAbstractValue
& other
) const;
212 bool isSupersetOf(const StructureSet
& other
) const;
213 bool isSupersetOf(const StructureAbstractValue
& other
) const
215 return other
.isSubsetOf(*this);
218 bool overlaps(const StructureSet
& other
) const;
219 bool overlaps(const StructureAbstractValue
& other
) const;
221 void validateReferences(const TrackedReferences
&) const;
224 static const uintptr_t clobberedFlag
= StructureSet::reservedFlag
;
225 static const uintptr_t topValue
= StructureSet::reservedValue
;
226 static const unsigned polymorphismLimit
= 10;
227 static const unsigned clobberedSupremacyThreshold
= 2;
229 void filterSlow(SpeculatedType type
);
230 bool mergeSlow(const StructureAbstractValue
& other
);
232 bool equalsSlow(const StructureAbstractValue
& other
) const;
234 void makeTopWhenThin()
236 ASSERT(m_set
.isThin());
237 m_set
.m_pointer
= topValue
;
240 bool mergeNotTop(const StructureSet
& other
);
242 void setClobbered(bool clobbered
)
244 ASSERT(!isTop() || !clobbered
);
245 m_set
.setReservedFlag(clobbered
);
251 } } // namespace JSC::DFG
253 #endif // ENABLE(DFG_JIT)
255 #endif // DFGStructureAbstractValue_h