]> git.saurik.com Git - apple/javascriptcore.git/blame - dfg/DFGAbstractValue.h
JavaScriptCore-7600.1.4.17.5.tar.gz
[apple/javascriptcore.git] / dfg / DFGAbstractValue.h
CommitLineData
6fe7ccc8 1/*
81345200 2 * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
6fe7ccc8
A
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
12 *
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.
24 */
25
26#ifndef DFGAbstractValue_h
27#define DFGAbstractValue_h
28
6fe7ccc8
A
29#if ENABLE(DFG_JIT)
30
93a37866 31#include "ArrayProfile.h"
81345200
A
32#include "DFGFiltrationResult.h"
33#include "DFGNodeFlags.h"
93a37866 34#include "DFGStructureAbstractValue.h"
6fe7ccc8 35#include "JSCell.h"
93a37866 36#include "SpeculatedType.h"
81345200 37#include "DumpContext.h"
6fe7ccc8
A
38#include "StructureSet.h"
39
40namespace JSC { namespace DFG {
41
81345200
A
42class Graph;
43struct Node;
44
93a37866
A
45struct AbstractValue {
46 AbstractValue()
47 : m_type(SpecNone)
48 , m_arrayModes(0)
6fe7ccc8 49 {
6fe7ccc8
A
50 }
51
52 void clear()
53 {
93a37866
A
54 m_type = SpecNone;
55 m_arrayModes = 0;
56 m_currentKnownStructure.clear();
57 m_futurePossibleStructure.clear();
58 m_value = JSValue();
59 checkConsistency();
6fe7ccc8
A
60 }
61
81345200
A
62 bool isClear() const { return m_type == SpecNone; }
63 bool operator!() const { return isClear(); }
64
65 void makeHeapTop()
6fe7ccc8 66 {
81345200 67 makeTop(SpecHeapTop);
6fe7ccc8
A
68 }
69
81345200 70 void makeBytecodeTop()
6fe7ccc8 71 {
81345200 72 makeTop(SpecBytecodeTop);
6fe7ccc8
A
73 }
74
93a37866 75 void clobberStructures()
6fe7ccc8 76 {
93a37866
A
77 if (m_type & SpecCell) {
78 m_currentKnownStructure.makeTop();
79 clobberArrayModes();
80 } else {
81 ASSERT(m_currentKnownStructure.isClear());
82 ASSERT(!m_arrayModes);
6fe7ccc8 83 }
93a37866 84 checkConsistency();
6fe7ccc8 85 }
6fe7ccc8 86
93a37866 87 void clobberValue()
6fe7ccc8 88 {
93a37866 89 m_value = JSValue();
6fe7ccc8
A
90 }
91
81345200 92 bool isHeapTop() const
6fe7ccc8 93 {
81345200 94 return (m_type | SpecHeapTop) == m_type && m_currentKnownStructure.isTop() && m_futurePossibleStructure.isTop();
6fe7ccc8
A
95 }
96
93a37866 97 bool valueIsTop() const
6fe7ccc8 98 {
93a37866 99 return !m_value && m_type;
6fe7ccc8
A
100 }
101
93a37866 102 JSValue value() const
6fe7ccc8 103 {
93a37866 104 return m_value;
6fe7ccc8
A
105 }
106
81345200 107 static AbstractValue heapTop()
6fe7ccc8 108 {
93a37866 109 AbstractValue result;
81345200 110 result.makeHeapTop();
93a37866 111 return result;
6fe7ccc8
A
112 }
113
81345200
A
114 void setMostSpecific(Graph&, JSValue);
115 void set(Graph&, JSValue);
116 void set(Graph&, Structure*);
6fe7ccc8 117
81345200 118 void setType(SpeculatedType type)
6fe7ccc8 119 {
93a37866
A
120 if (type & SpecCell) {
121 m_currentKnownStructure.makeTop();
122 m_futurePossibleStructure.makeTop();
123 m_arrayModes = ALL_ARRAY_MODES;
124 } else {
125 m_currentKnownStructure.clear();
126 m_futurePossibleStructure.clear();
127 m_arrayModes = 0;
128 }
6fe7ccc8 129 m_type = type;
93a37866 130 m_value = JSValue();
6fe7ccc8
A
131 checkConsistency();
132 }
133
81345200
A
134 void fixTypeForRepresentation(NodeFlags representation);
135 void fixTypeForRepresentation(Node*);
136
6fe7ccc8
A
137 bool operator==(const AbstractValue& other) const
138 {
93a37866
A
139 return m_type == other.m_type
140 && m_arrayModes == other.m_arrayModes
141 && m_currentKnownStructure == other.m_currentKnownStructure
142 && m_futurePossibleStructure == other.m_futurePossibleStructure
143 && m_value == other.m_value;
144 }
145 bool operator!=(const AbstractValue& other) const
146 {
147 return !(*this == other);
6fe7ccc8
A
148 }
149
150 bool merge(const AbstractValue& other)
151 {
93a37866
A
152 if (other.isClear())
153 return false;
154
155#if !ASSERT_DISABLED
156 AbstractValue oldMe = *this;
157#endif
158 bool result = false;
159 if (isClear()) {
160 *this = other;
161 result = !other.isClear();
162 } else {
163 result |= mergeSpeculation(m_type, other.m_type);
164 result |= mergeArrayModes(m_arrayModes, other.m_arrayModes);
165 result |= m_currentKnownStructure.addAll(other.m_currentKnownStructure);
166 result |= m_futurePossibleStructure.addAll(other.m_futurePossibleStructure);
167 if (m_value != other.m_value) {
168 result |= !!m_value;
169 m_value = JSValue();
170 }
171 }
6fe7ccc8 172 checkConsistency();
93a37866 173 ASSERT(result == (*this != oldMe));
6fe7ccc8
A
174 return result;
175 }
176
93a37866 177 void merge(SpeculatedType type)
6fe7ccc8 178 {
93a37866 179 mergeSpeculation(m_type, type);
6fe7ccc8 180
93a37866
A
181 if (type & SpecCell) {
182 m_currentKnownStructure.makeTop();
183 m_futurePossibleStructure.makeTop();
184 m_arrayModes = ALL_ARRAY_MODES;
185 }
186 m_value = JSValue();
6fe7ccc8
A
187
188 checkConsistency();
189 }
190
81345200 191 bool couldBeType(SpeculatedType desiredType)
6fe7ccc8 192 {
81345200 193 return !!(m_type & desiredType);
93a37866
A
194 }
195
81345200 196 bool isType(SpeculatedType desiredType)
93a37866 197 {
81345200 198 return !(m_type & ~desiredType);
6fe7ccc8
A
199 }
200
81345200 201 FiltrationResult filter(Graph&, const StructureSet&);
6fe7ccc8 202
81345200 203 FiltrationResult filterArrayModes(ArrayModes);
93a37866 204
81345200
A
205 FiltrationResult filter(SpeculatedType);
206
207 FiltrationResult filterByValue(JSValue);
93a37866
A
208
209 bool validate(JSValue value) const
210 {
81345200 211 if (isHeapTop())
6fe7ccc8
A
212 return true;
213
93a37866
A
214 if (!!m_value && m_value != value)
215 return false;
216
217 if (mergeSpeculations(m_type, speculationFromValue(value)) != m_type)
218 return false;
219
220 if (value.isEmpty()) {
221 ASSERT(m_type & SpecEmpty);
222 return true;
223 }
224
225 if (!!value && value.isCell()) {
226 ASSERT(m_type & SpecCell);
227 Structure* structure = value.asCell()->structure();
228 return m_currentKnownStructure.contains(structure)
229 && m_futurePossibleStructure.contains(structure)
230 && (m_arrayModes & asArrayModes(structure->indexingType()));
6fe7ccc8
A
231 }
232
233 return true;
234 }
235
93a37866
A
236 Structure* bestProvenStructure() const
237 {
238 if (m_currentKnownStructure.hasSingleton())
239 return m_currentKnownStructure.singleton();
240 if (m_futurePossibleStructure.hasSingleton())
241 return m_futurePossibleStructure.singleton();
242 return 0;
243 }
244
81345200 245 bool hasClobberableState() const
6fe7ccc8 246 {
81345200
A
247 return m_currentKnownStructure.isNeitherClearNorTop()
248 || !arrayModesAreClearOrTop(m_arrayModes);
6fe7ccc8
A
249 }
250
81345200
A
251#if ASSERT_DISABLED
252 void checkConsistency() const { }
253#else
254 void checkConsistency() const;
255#endif
256
257 void dumpInContext(PrintStream&, DumpContext*) const;
258 void dump(PrintStream&) const;
93a37866
A
259
260 // A great way to think about the difference between m_currentKnownStructure and
261 // m_futurePossibleStructure is to consider these four examples:
262 //
263 // 1) x = foo();
264 //
265 // In this case x's m_currentKnownStructure and m_futurePossibleStructure will
266 // both be TOP, since we don't know anything about x for sure, yet.
267 //
268 // 2) x = foo();
269 // y = x.f;
270 //
271 // Where x will later have a new property added to it, 'g'. Because of the
81345200 272 // known but not-yet-executed property addition, x's current structure will
93a37866
A
273 // not be watchpointable; hence we have no way of statically bounding the set
274 // of possible structures that x may have if a clobbering event happens. So,
275 // x's m_currentKnownStructure will be whatever structure we check to get
276 // property 'f', and m_futurePossibleStructure will be TOP.
277 //
278 // 3) x = foo();
279 // y = x.f;
280 //
281 // Where x has a terminal structure that is still watchpointable. In this case,
282 // x's m_currentKnownStructure and m_futurePossibleStructure will both be
283 // whatever structure we checked for when getting 'f'.
284 //
285 // 4) x = foo();
286 // y = x.f;
287 // bar();
288 //
289 // Where x has a terminal structure that is still watchpointable. In this
290 // case, m_currentKnownStructure will be TOP because bar() may potentially
291 // change x's structure and we have no way of proving otherwise, but
292 // x's m_futurePossibleStructure will be whatever structure we had checked
293 // when getting property 'f'.
294
295 // NB. All fields in this struct must have trivial destructors.
296
297 // This is a proven constraint on the structures that this value can have right
298 // now. The structure of the current value must belong to this set. The set may
299 // be TOP, indicating that it is the set of all possible structures, in which
300 // case the current value can have any structure. The set may be BOTTOM (empty)
301 // in which case this value cannot be a cell. This is all subject to change
302 // anytime a new value is assigned to this one, anytime there is a control flow
303 // merge, or most crucially, anytime a side-effect or structure check happens.
304 // In case of a side-effect, we typically must assume that any value may have
305 // had its structure changed, hence contravening our proof. We make the proof
306 // valid again by switching this to TOP (i.e. claiming that we have proved that
307 // this value may have any structure). Of note is that the proof represented by
308 // this field is not subject to structure transition watchpoints - even if one
309 // fires, we can be sure that this proof is still valid.
310 StructureAbstractValue m_currentKnownStructure;
311
312 // This is a proven constraint on the structures that this value can have now
313 // or any time in the future subject to the structure transition watchpoints of
314 // all members of this set not having fired. This set is impervious to side-
315 // effects; even if one happens the side-effect can only cause the value to
316 // change to at worst another structure that is also a member of this set. But,
317 // the theorem being proved by this field is predicated upon there not being
318 // any new structure transitions introduced into any members of this set. In
319 // cases where there is no way for us to guard this happening, the set must be
320 // TOP. But in cases where we can guard new structure transitions (all members
321 // of the set have still-valid structure transition watchpoints) then this set
322 // will be finite. Anytime that we make use of the finite nature of this set,
323 // we must first issue a structure transition watchpoint, which will effectively
324 // result in m_currentKnownStructure being filtered according to
325 // m_futurePossibleStructure.
326 StructureAbstractValue m_futurePossibleStructure;
327
328 // This is a proven constraint on the possible types that this value can have
329 // now or any time in the future, unless it is reassigned. This field is
330 // impervious to side-effects unless the side-effect can reassign the value
331 // (for example if we're talking about a captured variable). The relationship
332 // between this field, and the structure fields above, is as follows. The
333 // fields above constraint the structures that a cell may have, but they say
334 // nothing about whether or not the value is known to be a cell. More formally,
335 // the m_currentKnownStructure is itself an abstract value that consists of the
336 // union of the set of all non-cell values and the set of cell values that have
337 // the given structure. This abstract value is then the intersection of the
338 // m_currentKnownStructure and the set of values whose type is m_type. So, for
339 // example if m_type is SpecFinal|SpecInt32 and m_currentKnownStructure is
340 // [0x12345] then this abstract value corresponds to the set of all integers
341 // unified with the set of all objects with structure 0x12345.
342 SpeculatedType m_type;
343
344 // This is a proven constraint on the possible indexing types that this value
345 // can have right now. It also implicitly constraints the set of structures
346 // that the value may have right now, since a structure has an immutable
347 // indexing type. This is subject to change upon reassignment, or any side
348 // effect that makes non-obvious changes to the heap.
349 ArrayModes m_arrayModes;
350
351 // This is a proven constraint on the possible values that this value can
352 // have now or any time in the future, unless it is reassigned. Note that this
353 // implies nothing about the structure. Oddly, JSValue() (i.e. the empty value)
354 // means either BOTTOM or TOP depending on the state of m_type: if m_type is
355 // BOTTOM then JSValue() means BOTTOM; if m_type is not BOTTOM then JSValue()
356 // means TOP.
357 JSValue m_value;
358
359private:
360 void clobberArrayModes()
6fe7ccc8 361 {
93a37866
A
362 // FIXME: We could make this try to predict the set of array modes that this object
363 // could have in the future. For now, just do the simple thing.
364 m_arrayModes = ALL_ARRAY_MODES;
365 }
366
81345200 367 bool validateType(JSValue value) const
93a37866 368 {
81345200
A
369 if (isHeapTop())
370 return true;
371
372 // Constant folding always represents Int52's in a double (i.e. Int52AsDouble).
373 // So speculationFromValue(value) for an Int52 value will return Int52AsDouble,
374 // and that's fine - the type validates just fine.
375 SpeculatedType type = m_type;
376 if (type & SpecInt52)
377 type |= SpecInt52AsDouble;
378
379 if (mergeSpeculations(type, speculationFromValue(value)) != type)
380 return false;
381
382 if (value.isEmpty()) {
383 ASSERT(m_type & SpecEmpty);
384 return true;
385 }
386
387 return true;
93a37866
A
388 }
389
81345200 390 void makeTop(SpeculatedType top)
93a37866 391 {
81345200
A
392 m_type |= top;
393 m_arrayModes = ALL_ARRAY_MODES;
394 m_currentKnownStructure.makeTop();
395 m_futurePossibleStructure.makeTop();
93a37866 396 m_value = JSValue();
81345200 397 checkConsistency();
93a37866
A
398 }
399
81345200 400 void setFuturePossibleStructure(Graph&, Structure*);
93a37866 401
81345200
A
402 void filterValueByType();
403 void filterArrayModesByType();
404
405 bool shouldBeClear() const;
406 FiltrationResult normalizeClarity();
6fe7ccc8
A
407};
408
409} } // namespace JSC::DFG
410
411#endif // ENABLE(DFG_JIT)
412
413#endif // DFGAbstractValue_h
414
415