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 DFGAbstractValue_h
27 #define DFGAbstractValue_h
31 #include "ArrayProfile.h"
32 #include "DFGFiltrationResult.h"
33 #include "DFGFrozenValue.h"
34 #include "DFGNodeFlags.h"
35 #include "DFGStructureAbstractValue.h"
36 #include "DFGStructureClobberState.h"
38 #include "SpeculatedType.h"
39 #include "DumpContext.h"
40 #include "StructureSet.h"
44 class TrackedReferences
;
51 struct AbstractValue
{
67 bool isClear() const { return m_type
== SpecNone
; }
68 bool operator!() const { return isClear(); }
75 void makeBytecodeTop()
77 makeTop(SpecBytecodeTop
);
85 void clobberStructures()
87 if (m_type
& SpecCell
) {
88 m_structure
.clobber();
91 ASSERT(m_structure
.isClear());
92 ASSERT(!m_arrayModes
);
97 static void clobberStructuresFor(AbstractValue
& value
)
99 value
.clobberStructures();
102 void observeInvalidationPoint()
104 m_structure
.observeInvalidationPoint();
108 static void observeInvalidationPointFor(AbstractValue
& value
)
110 value
.observeInvalidationPoint();
113 void observeTransition(Structure
* from
, Structure
* to
)
115 if (m_type
& SpecCell
) {
116 m_structure
.observeTransition(from
, to
);
117 observeIndexingTypeTransition(from
->indexingType(), to
->indexingType());
122 void observeTransitions(const TransitionVector
& vector
);
124 class TransitionObserver
{
126 TransitionObserver(Structure
* from
, Structure
* to
)
132 void operator()(AbstractValue
& value
)
134 value
.observeTransition(m_from
, m_to
);
141 class TransitionsObserver
{
143 TransitionsObserver(const TransitionVector
& vector
)
148 void operator()(AbstractValue
& value
)
150 value
.observeTransitions(m_vector
);
153 const TransitionVector
& m_vector
;
161 bool isHeapTop() const
163 return (m_type
| SpecHeapTop
) == m_type
164 && m_structure
.isTop()
165 && m_arrayModes
== ALL_ARRAY_MODES
169 bool valueIsTop() const
171 return !m_value
&& m_type
;
174 JSValue
value() const
179 static AbstractValue
heapTop()
181 AbstractValue result
;
182 result
.makeHeapTop();
186 static AbstractValue
bytecodeTop()
188 AbstractValue result
;
189 result
.makeBytecodeTop();
193 static AbstractValue
fullTop()
195 AbstractValue result
;
196 result
.makeFullTop();
200 void set(Graph
&, const FrozenValue
&, StructureClobberState
);
201 void set(Graph
&, Structure
*);
202 void set(Graph
&, const StructureSet
&);
204 // Set this value to represent the given set of types as precisely as possible.
205 void setType(Graph
&, SpeculatedType
);
207 // As above, but only valid for non-cell types.
208 void setType(SpeculatedType type
)
210 RELEASE_ASSERT(!(type
& SpecCell
));
218 void fixTypeForRepresentation(Graph
&, NodeFlags representation
, Node
* = nullptr);
219 void fixTypeForRepresentation(Graph
&, Node
*);
221 bool operator==(const AbstractValue
& other
) const
223 return m_type
== other
.m_type
224 && m_arrayModes
== other
.m_arrayModes
225 && m_structure
== other
.m_structure
226 && m_value
== other
.m_value
;
228 bool operator!=(const AbstractValue
& other
) const
230 return !(*this == other
);
233 bool merge(const AbstractValue
& other
)
239 AbstractValue oldMe
= *this;
244 result
= !other
.isClear();
246 result
|= mergeSpeculation(m_type
, other
.m_type
);
247 result
|= mergeArrayModes(m_arrayModes
, other
.m_arrayModes
);
248 result
|= m_structure
.merge(other
.m_structure
);
249 if (m_value
!= other
.m_value
) {
255 ASSERT(result
== (*this != oldMe
));
259 bool mergeOSREntryValue(Graph
&, JSValue
);
261 void merge(SpeculatedType type
)
263 mergeSpeculation(m_type
, type
);
265 if (type
& SpecCell
) {
266 m_structure
.makeTop();
267 m_arrayModes
= ALL_ARRAY_MODES
;
274 bool couldBeType(SpeculatedType desiredType
) const
276 return !!(m_type
& desiredType
);
279 bool isType(SpeculatedType desiredType
) const
281 return !(m_type
& ~desiredType
);
284 FiltrationResult
filter(Graph
&, const StructureSet
&);
285 FiltrationResult
filterArrayModes(ArrayModes
);
286 FiltrationResult
filter(SpeculatedType
);
287 FiltrationResult
filterByValue(const FrozenValue
& value
);
288 FiltrationResult
filter(const AbstractValue
&);
290 FiltrationResult
changeStructure(Graph
&, const StructureSet
&);
292 bool contains(Structure
*) const;
294 bool validate(JSValue value
) const
299 if (!!m_value
&& m_value
!= value
)
302 if (mergeSpeculations(m_type
, speculationFromValue(value
)) != m_type
)
305 if (value
.isEmpty()) {
306 ASSERT(m_type
& SpecEmpty
);
310 if (!!value
&& value
.isCell()) {
311 ASSERT(m_type
& SpecCell
);
312 Structure
* structure
= value
.asCell()->structure();
313 return m_structure
.contains(structure
)
314 && (m_arrayModes
& asArrayModes(structure
->indexingType()));
320 bool hasClobberableState() const
322 return m_structure
.isNeitherClearNorTop()
323 || !arrayModesAreClearOrTop(m_arrayModes
);
327 void checkConsistency() const { }
328 void assertIsRegistered(Graph
&) const { }
330 void checkConsistency() const;
331 void assertIsRegistered(Graph
&) const;
334 void dumpInContext(PrintStream
&, DumpContext
*) const;
335 void dump(PrintStream
&) const;
337 void validateReferences(const TrackedReferences
&);
339 // This is a proven constraint on the structures that this value can have right
340 // now. The structure of the current value must belong to this set. The set may
341 // be TOP, indicating that it is the set of all possible structures, in which
342 // case the current value can have any structure. The set may be BOTTOM (empty)
343 // in which case this value cannot be a cell. This is all subject to change
344 // anytime a new value is assigned to this one, anytime there is a control flow
345 // merge, or most crucially, anytime a side-effect or structure check happens.
346 // In case of a side-effect, we must assume that any value with a structure that
347 // isn't being watched may have had its structure changed, hence contravening
348 // our proof. In such a case we make the proof valid again by switching this to
349 // TOP (i.e. claiming that we have proved that this value may have any
351 StructureAbstractValue m_structure
;
353 // This is a proven constraint on the possible types that this value can have
354 // now or any time in the future, unless it is reassigned. This field is
355 // impervious to side-effects. The relationship between this field, and the
356 // structure fields above, is as follows. The fields above constraint the
357 // structures that a cell may have, but they say nothing about whether or not
358 // the value is known to be a cell. More formally, the m_structure is itself an
359 // abstract value that consists of the union of the set of all non-cell values
360 // and the set of cell values that have the given structure. This abstract
361 // value is then the intersection of the m_structure and the set of values
362 // whose type is m_type. So, for example if m_type is SpecFinal|SpecInt32 and
363 // m_structure is [0x12345] then this abstract value corresponds to the set of
364 // all integers unified with the set of all objects with structure 0x12345.
365 SpeculatedType m_type
;
367 // This is a proven constraint on the possible indexing types that this value
368 // can have right now. It also implicitly constraints the set of structures
369 // that the value may have right now, since a structure has an immutable
370 // indexing type. This is subject to change upon reassignment, or any side
371 // effect that makes non-obvious changes to the heap.
372 ArrayModes m_arrayModes
;
374 // This is a proven constraint on the possible values that this value can
375 // have now or any time in the future, unless it is reassigned. Note that this
376 // implies nothing about the structure. Oddly, JSValue() (i.e. the empty value)
377 // means either BOTTOM or TOP depending on the state of m_type: if m_type is
378 // BOTTOM then JSValue() means BOTTOM; if m_type is not BOTTOM then JSValue()
379 // means TOP. Also note that this value isn't necessarily known to the GC
380 // (strongly or even weakly - it may be an "fragile" value, see
381 // DFGValueStrength.h). If you perform any optimization based on a cell m_value
382 // that requires that the value be kept alive, you must call freeze() on that
383 // value, which will turn it into a weak value.
387 void clobberArrayModes()
389 // FIXME: We could make this try to predict the set of array modes that this object
390 // could have in the future. For now, just do the simple thing.
391 m_arrayModes
= ALL_ARRAY_MODES
;
394 void observeIndexingTypeTransition(IndexingType from
, IndexingType to
)
396 if (m_arrayModes
& asArrayModes(from
))
397 m_arrayModes
|= asArrayModes(to
);
400 bool validateType(JSValue value
) const
405 // Constant folding always represents Int52's in a double (i.e. Int52AsDouble).
406 // So speculationFromValue(value) for an Int52 value will return Int52AsDouble,
407 // and that's fine - the type validates just fine.
408 SpeculatedType type
= m_type
;
409 if (type
& SpecInt52
)
410 type
|= SpecInt52AsDouble
;
412 if (mergeSpeculations(type
, speculationFromValue(value
)) != type
)
415 if (value
.isEmpty()) {
416 ASSERT(m_type
& SpecEmpty
);
423 void makeTop(SpeculatedType top
)
426 m_arrayModes
= ALL_ARRAY_MODES
;
427 m_structure
.makeTop();
432 void filterValueByType();
433 void filterArrayModesByType();
435 bool shouldBeClear() const;
436 FiltrationResult
normalizeClarity();
437 FiltrationResult
normalizeClarity(Graph
&);
440 } } // namespace JSC::DFG
442 #endif // ENABLE(DFG_JIT)
444 #endif // DFGAbstractValue_h