2 * Copyright (C) 2011 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
29 #include <wtf/Platform.h>
34 #include "PredictedType.h"
35 #include "StructureSet.h"
37 namespace JSC
{ namespace DFG
{
39 class StructureAbstractValue
{
41 StructureAbstractValue()
46 StructureAbstractValue(Structure
* structure
)
47 : m_structure(structure
)
51 StructureAbstractValue(const StructureSet
& set
)
63 m_structure
= topValue();
75 m_structure
= topValue();
78 static StructureAbstractValue
top()
80 StructureAbstractValue value
;
85 void add(Structure
* structure
)
87 ASSERT(!contains(structure
) && !isTop());
91 m_structure
= structure
;
94 bool addAll(const StructureSet
& other
)
96 if (isTop() || !other
.size())
98 if (other
.size() > 1) {
103 m_structure
= other
[0];
106 if (m_structure
== other
[0])
112 bool addAll(const StructureAbstractValue
& other
)
114 if (!other
.m_structure
)
123 if (m_structure
== other
.m_structure
)
128 m_structure
= other
.m_structure
;
132 bool contains(Structure
* structure
) const
136 if (m_structure
== structure
)
141 bool isSubsetOf(const StructureSet
& other
) const
147 return other
.contains(m_structure
);
150 bool doesNotContainAnyOtherThan(Structure
* structure
) const
156 return m_structure
== structure
;
159 bool isSupersetOf(const StructureSet
& other
) const
165 if (other
.size() > 1)
167 return m_structure
== other
[0];
170 bool isSubsetOf(const StructureAbstractValue
& other
) const
177 if (other
.m_structure
)
178 return m_structure
== other
.m_structure
;
184 bool isSupersetOf(const StructureAbstractValue
& other
) const
186 return other
.isSubsetOf(*this);
189 void filter(const StructureSet
& other
)
195 switch (other
.size()) {
201 m_structure
= other
[0];
209 if (other
.contains(m_structure
))
215 void filter(const StructureAbstractValue
& other
)
218 m_structure
= other
.m_structure
;
221 if (m_structure
== other
.m_structure
)
228 void filter(PredictedType other
)
230 if (!(other
& PredictCell
)) {
238 if (!(predictionFromStructure(m_structure
) & other
))
247 bool isTop() const { return m_structure
== topValue(); }
249 bool isClearOrTop() const { return m_structure
<= topValue(); }
250 bool isNeitherClearNorTop() const { return !isClearOrTop(); }
255 return !!m_structure
;
258 Structure
* at(size_t i
) const
262 ASSERT_UNUSED(i
, !i
);
266 Structure
* operator[](size_t i
) const
271 Structure
* last() const
276 PredictedType
predictionFromStructures() const
282 return predictionFromStructure(m_structure
);
285 bool operator==(const StructureAbstractValue
& other
) const
287 return m_structure
== other
.m_structure
;
290 void dump(FILE* out
) const
299 fprintf(out
, "%p", m_structure
);
304 static Structure
* topValue() { return reinterpret_cast<Structure
*>(1); }
306 // This can only remember one structure at a time.
307 Structure
* m_structure
;
310 struct AbstractValue
{
312 : m_type(PredictNone
)
318 m_type
= PredictNone
;
325 return m_type
== PredictNone
&& m_structure
.isClear();
331 m_structure
.makeTop();
335 void clobberStructures()
337 if (m_type
& PredictCell
)
338 m_structure
.makeTop();
340 ASSERT(m_structure
.isClear());
346 return m_type
== PredictTop
&& m_structure
.isTop();
349 static AbstractValue
top()
351 AbstractValue result
;
356 void set(JSValue value
)
360 m_structure
.add(value
.asCell()->structure());
362 m_type
= predictionFromValue(value
);
367 void set(Structure
* structure
)
370 m_structure
.add(structure
);
372 m_type
= predictionFromStructure(structure
);
377 void set(PredictedType type
)
379 if (type
& PredictCell
)
380 m_structure
.makeTop();
387 bool operator==(const AbstractValue
& other
) const
389 return m_type
== other
.m_type
&& m_structure
== other
.m_structure
;
392 bool merge(const AbstractValue
& other
)
394 bool result
= mergePrediction(m_type
, other
.m_type
) | m_structure
.addAll(other
.m_structure
);
399 void merge(PredictedType type
)
401 mergePrediction(m_type
, type
);
403 if (type
& PredictCell
)
404 m_structure
.makeTop();
409 void filter(const StructureSet
& other
)
411 m_type
&= other
.predictionFromStructures();
412 m_structure
.filter(other
);
414 // It's possible that prior to the above two statements we had (Foo, TOP), where
415 // Foo is a PredictedType that is disjoint with the passed StructureSet. In that
416 // case, we will now have (None, [someStructure]). In general, we need to make
417 // sure that new information gleaned from the PredictedType needs to be fed back
418 // into the information gleaned from the StructureSet.
419 m_structure
.filter(m_type
);
423 void filter(PredictedType type
)
425 if (type
== PredictTop
)
429 // It's possible that prior to this filter() call we had, say, (Final, TOP), and
430 // the passed type is Array. At this point we'll have (None, TOP). The best way
431 // to ensure that the structure filtering does the right thing is to filter on
432 // the new type (None) rather than the one passed (Array).
433 m_structure
.filter(m_type
);
437 bool validate(JSValue value
) const
442 if (mergePredictions(m_type
, predictionFromValue(value
)) != m_type
)
445 if (value
.isEmpty()) {
446 ASSERT(m_type
& PredictEmpty
);
450 if (m_structure
.isTop())
453 if (value
.isCell()) {
454 ASSERT(m_type
& PredictCell
);
455 return m_structure
.contains(value
.asCell()->structure());
461 void checkConsistency() const
463 if (!(m_type
& PredictCell
))
464 ASSERT(m_structure
.isClear());
466 // Note that it's possible for a prediction like (Final, []). This really means that
467 // the value is bottom and that any code that uses the value is unreachable. But
468 // we don't want to get pedantic about this as it would only increase the computational
469 // complexity of the code.
472 void dump(FILE* out
) const
474 fprintf(out
, "(%s, ", predictionToString(m_type
));
475 m_structure
.dump(out
);
479 StructureAbstractValue m_structure
;
480 PredictedType m_type
;
483 } } // namespace JSC::DFG
485 #endif // ENABLE(DFG_JIT)
487 #endif // DFGAbstractValue_h