2 * Copyright (C) 2013, 2014 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.
27 #include "DFGAbstractValue.h"
32 #include "JSCInlines.h"
34 namespace JSC
{ namespace DFG
{
36 void AbstractValue::setMostSpecific(Graph
& graph
, JSValue value
)
38 if (!!value
&& value
.isCell()) {
39 Structure
* structure
= value
.asCell()->structure();
40 m_currentKnownStructure
= structure
;
41 setFuturePossibleStructure(graph
, structure
);
42 m_arrayModes
= asArrayModes(structure
->indexingType());
44 m_currentKnownStructure
.clear();
45 m_futurePossibleStructure
.clear();
49 m_type
= speculationFromValue(value
);
55 void AbstractValue::set(Graph
& graph
, JSValue value
)
57 if (!!value
&& value
.isCell()) {
58 m_currentKnownStructure
.makeTop();
59 Structure
* structure
= value
.asCell()->structure();
60 setFuturePossibleStructure(graph
, structure
);
61 m_arrayModes
= asArrayModes(structure
->indexingType());
64 m_currentKnownStructure
.clear();
65 m_futurePossibleStructure
.clear();
69 m_type
= speculationFromValue(value
);
75 void AbstractValue::set(Graph
& graph
, Structure
* structure
)
77 m_currentKnownStructure
= structure
;
78 setFuturePossibleStructure(graph
, structure
);
79 m_arrayModes
= asArrayModes(structure
->indexingType());
80 m_type
= speculationFromStructure(structure
);
86 void AbstractValue::fixTypeForRepresentation(NodeFlags representation
)
88 if (representation
== NodeResultDouble
) {
90 ASSERT(m_value
.isNumber());
91 if (m_value
.isInt32())
92 m_value
= jsDoubleNumber(m_value
.asNumber());
94 if (m_type
& SpecMachineInt
) {
95 m_type
&= ~SpecMachineInt
;
96 m_type
|= SpecInt52AsDouble
;
98 if (m_type
& ~SpecFullDouble
) {
100 dataLog("Abstract value ", *this, " for double node has type outside SpecFullDouble.\n");
103 } else if (representation
== NodeResultInt52
) {
104 if (m_type
& SpecInt52AsDouble
) {
105 m_type
&= ~SpecInt52AsDouble
;
108 if (m_type
& ~SpecMachineInt
) {
110 dataLog("Abstract value ", *this, " for int52 node has type outside SpecMachineInt.\n");
114 if (m_type
& SpecInt52
) {
115 m_type
&= ~SpecInt52
;
116 m_type
|= SpecInt52AsDouble
;
118 if (m_type
& ~SpecBytecodeTop
) {
120 dataLog("Abstract value ", *this, " for value node has type outside SpecBytecodeTop.\n");
128 void AbstractValue::fixTypeForRepresentation(Node
* node
)
130 fixTypeForRepresentation(node
->result());
133 FiltrationResult
AbstractValue::filter(Graph
& graph
, const StructureSet
& other
)
138 // FIXME: This could be optimized for the common case of m_type not
139 // having structures, array modes, or a specific value.
140 // https://bugs.webkit.org/show_bug.cgi?id=109663
142 m_type
&= other
.speculationFromStructures();
143 m_arrayModes
&= other
.arrayModesFromStructures();
144 m_currentKnownStructure
.filter(other
);
146 // It's possible that prior to the above two statements we had (Foo, TOP), where
147 // Foo is a SpeculatedType that is disjoint with the passed StructureSet. In that
148 // case, we will now have (None, [someStructure]). In general, we need to make
149 // sure that new information gleaned from the SpeculatedType needs to be fed back
150 // into the information gleaned from the StructureSet.
151 m_currentKnownStructure
.filter(m_type
);
153 if (m_currentKnownStructure
.hasSingleton())
154 setFuturePossibleStructure(graph
, m_currentKnownStructure
.singleton());
156 filterArrayModesByType();
158 return normalizeClarity();
161 FiltrationResult
AbstractValue::filterArrayModes(ArrayModes arrayModes
)
169 m_arrayModes
&= arrayModes
;
170 return normalizeClarity();
173 FiltrationResult
AbstractValue::filter(SpeculatedType type
)
175 if ((m_type
& type
) == m_type
)
180 // It's possible that prior to this filter() call we had, say, (Final, TOP), and
181 // the passed type is Array. At this point we'll have (None, TOP). The best way
182 // to ensure that the structure filtering does the right thing is to filter on
183 // the new type (None) rather than the one passed (Array).
184 m_currentKnownStructure
.filter(m_type
);
185 m_futurePossibleStructure
.filter(m_type
);
186 filterArrayModesByType();
188 return normalizeClarity();
191 FiltrationResult
AbstractValue::filterByValue(JSValue value
)
193 FiltrationResult result
= filter(speculationFromValue(value
));
199 void AbstractValue::setFuturePossibleStructure(Graph
& graph
, Structure
* structure
)
202 if (graph
.watchpoints().isStillValid(structure
->transitionWatchpointSet()))
203 m_futurePossibleStructure
= structure
;
205 m_futurePossibleStructure
.makeTop();
208 void AbstractValue::filterValueByType()
210 // We could go further, and ensure that if the futurePossibleStructure contravenes
211 // the value, then we could clear both of those things. But that's unlikely to help
212 // in any realistic scenario, so we don't do it. Simpler is better.
215 // The type is still non-empty. It may be that the new type renders
216 // the value empty because it contravenes the constant value we had.
217 if (m_value
&& !validateType(m_value
))
222 // The type has been rendered empty. That means that the value must now be invalid,
224 ASSERT(!m_value
|| !validateType(m_value
));
228 void AbstractValue::filterArrayModesByType()
230 if (!(m_type
& SpecCell
))
232 else if (!(m_type
& ~SpecArray
))
233 m_arrayModes
&= ALL_ARRAY_ARRAY_MODES
;
235 // NOTE: If m_type doesn't have SpecArray set, that doesn't mean that the
236 // array modes have to be a subset of ALL_NON_ARRAY_ARRAY_MODES, since
237 // in the speculated type type-system, RegExpMatchesArry and ArrayPrototype
238 // are Otherobj (since they are not *exactly* JSArray) but in the ArrayModes
239 // type system they are arrays (since they expose the magical length
240 // property and are otherwise allocated using array allocation). Hence the
241 // following would be wrong:
243 // if (!(m_type & SpecArray))
244 // m_arrayModes &= ALL_NON_ARRAY_ARRAY_MODES;
247 bool AbstractValue::shouldBeClear() const
249 if (m_type
== SpecNone
)
252 if (!(m_type
& ~SpecCell
)
254 || m_currentKnownStructure
.isClear()))
260 FiltrationResult
AbstractValue::normalizeClarity()
262 // It's useful to be able to quickly check if an abstract value is clear.
263 // This normalizes everything to make that easy.
265 FiltrationResult result
;
267 if (shouldBeClear()) {
269 result
= Contradiction
;
271 result
= FiltrationOK
;
279 void AbstractValue::checkConsistency() const
281 if (!(m_type
& SpecCell
)) {
282 ASSERT(m_currentKnownStructure
.isClear());
283 ASSERT(m_futurePossibleStructure
.isClear());
284 ASSERT(!m_arrayModes
);
291 SpeculatedType type
= m_type
;
292 // This relaxes the assertion below a bit, since we don't know the representation of the
294 if (type
& SpecInt52
)
295 type
|= SpecInt52AsDouble
;
296 ASSERT(mergeSpeculations(type
, speculationFromValue(m_value
)) == type
);
299 // Note that it's possible for a prediction like (Final, []). This really means that
300 // the value is bottom and that any code that uses the value is unreachable. But
301 // we don't want to get pedantic about this as it would only increase the computational
302 // complexity of the code.
306 void AbstractValue::dump(PrintStream
& out
) const
308 dumpInContext(out
, 0);
311 void AbstractValue::dumpInContext(PrintStream
& out
, DumpContext
* context
) const
313 out
.print("(", SpeculationDump(m_type
));
314 if (m_type
& SpecCell
) {
316 ", ", ArrayModesDump(m_arrayModes
), ", ",
317 inContext(m_currentKnownStructure
, context
), ", ",
318 inContext(m_futurePossibleStructure
, context
));
321 out
.print(", ", inContext(m_value
, context
));
325 } } // namespace JSC::DFG
327 #endif // ENABLE(DFG_JIT)