1/*
2 * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
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 DFGStructureAbstractValue_h
27#define DFGStructureAbstractValue_h
28
29#include <wtf/Platform.h>
30
31#if ENABLE(DFG_JIT)
32
33#include "JSCell.h"
34#include "SpeculatedType.h"
35#include "StructureSet.h"
36
37namespace JSC { namespace DFG {
38
39class StructureAbstractValue {
40public:
41    StructureAbstractValue()
42        : m_structure(0)
43    {
44    }
45
46    StructureAbstractValue(Structure* structure)
47        : m_structure(structure)
48    {
49    }
50
51    StructureAbstractValue(const StructureSet& set)
52    {
53        switch (set.size()) {
54        case 0:
55            m_structure = 0;
56            break;
57
58        case 1:
59            m_structure = set[0];
60            break;
61
62        default:
63            m_structure = topValue();
64            break;
65        }
66    }
67
68    void clear()
69    {
70        m_structure = 0;
71    }
72
73    void makeTop()
74    {
75        m_structure = topValue();
76    }
77
78    static StructureAbstractValue top()
79    {
80        StructureAbstractValue value;
81        value.makeTop();
82        return value;
83    }
84
85    void add(Structure* structure)
86    {
87        ASSERT(!contains(structure) && !isTop());
88        if (m_structure)
89            makeTop();
90        else
91            m_structure = structure;
92    }
93
94    bool addAll(const StructureSet& other)
95    {
96        if (isTop() || !other.size())
97            return false;
98        if (other.size() > 1) {
99            makeTop();
100            return true;
101        }
102        if (!m_structure) {
103            m_structure = other[0];
104            return true;
105        }
106        if (m_structure == other[0])
107            return false;
108        makeTop();
109        return true;
110    }
111
112    bool addAll(const StructureAbstractValue& other)
113    {
114        if (!other.m_structure)
115            return false;
116        if (isTop())
117            return false;
118        if (other.isTop()) {
119            makeTop();
120            return true;
121        }
122        if (m_structure) {
123            if (m_structure == other.m_structure)
124                return false;
125            makeTop();
126            return true;
127        }
128        m_structure = other.m_structure;
129        return true;
130    }
131
132    bool contains(Structure* structure) const
133    {
134        if (isTop())
135            return true;
136        if (m_structure == structure)
137            return true;
138        return false;
139    }
140
141    bool isSubsetOf(const StructureSet& other) const
142    {
143        if (isTop())
144            return false;
145        if (!m_structure)
146            return true;
147        return other.contains(m_structure);
148    }
149
150    bool doesNotContainAnyOtherThan(Structure* structure) const
151    {
152        if (isTop())
153            return false;
154        if (!m_structure)
155            return true;
156        return m_structure == structure;
157    }
158
159    bool isSupersetOf(const StructureSet& other) const
160    {
161        if (isTop())
162            return true;
163        if (!other.size())
164            return true;
165        if (other.size() > 1)
166            return false;
167        return m_structure == other[0];
168    }
169
170    bool isSubsetOf(const StructureAbstractValue& other) const
171    {
172        if (other.isTop())
173            return true;
174        if (isTop())
175            return false;
176        if (m_structure) {
177            if (other.m_structure)
178                return m_structure == other.m_structure;
179            return false;
180        }
181        return true;
182    }
183
184    bool isSupersetOf(const StructureAbstractValue& other) const
185    {
186        return other.isSubsetOf(*this);
187    }
188
189    void filter(const StructureSet& other)
190    {
191        if (!m_structure)
192            return;
193
194        if (isTop()) {
195            switch (other.size()) {
196            case 0:
197                m_structure = 0;
198                return;
199
200            case 1:
201                m_structure = other[0];
202                return;
203
204            default:
205                return;
206            }
207        }
208
209        if (other.contains(m_structure))
210            return;
211
212        m_structure = 0;
213    }
214
215    void filter(const StructureAbstractValue& other)
216    {
217        if (isTop()) {
218            m_structure = other.m_structure;
219            return;
220        }
221        if (m_structure == other.m_structure)
222            return;
223        if (other.isTop())
224            return;
225        m_structure = 0;
226    }
227
228    void filter(SpeculatedType other)
229    {
230        if (!(other & SpecCell)) {
231            clear();
232            return;
233        }
234
235        if (isClearOrTop())
236            return;
237
238        if (!(speculationFromStructure(m_structure) & other))
239            m_structure = 0;
240    }
241
242    bool isClear() const
243    {
244        return !m_structure;
245    }
246
247    bool isTop() const { return m_structure == topValue(); }
248
249    bool isClearOrTop() const { return m_structure <= topValue(); }
250    bool isNeitherClearNorTop() const { return !isClearOrTop(); }
251
252    size_t size() const
253    {
254        ASSERT(!isTop());
255        return !!m_structure;
256    }
257
258    Structure* at(size_t i) const
259    {
260        ASSERT(!isTop());
261        ASSERT(m_structure);
262        ASSERT_UNUSED(i, !i);
263        return m_structure;
264    }
265
266    Structure* operator[](size_t i) const
267    {
268        return at(i);
269    }
270
271    Structure* last() const
272    {
273        return at(0);
274    }
275
276    SpeculatedType speculationFromStructures() const
277    {
278        if (isTop())
279            return SpecCell;
280        if (isClear())
281            return SpecNone;
282        return speculationFromStructure(m_structure);
283    }
284
285    bool hasSingleton() const
286    {
287        return isNeitherClearNorTop();
288    }
289
290    Structure* singleton() const
291    {
292        ASSERT(isNeitherClearNorTop());
293        return m_structure;
294    }
295
296    bool operator==(const StructureAbstractValue& other) const
297    {
298        return m_structure == other.m_structure;
299    }
300
301    void dump(PrintStream& out) const
302    {
303        if (isTop()) {
304            out.print("TOP");
305            return;
306        }
307
308        out.print("[");
309        if (m_structure)
310            out.print(RawPointer(m_structure), "(", m_structure->classInfo()->className, ")");
311        out.print("]");
312    }
313
314private:
315    static Structure* topValue() { return reinterpret_cast<Structure*>(1); }
316
317    // NB. This must have a trivial destructor.
318
319    // This can only remember one structure at a time.
320    Structure* m_structure;
321};
322
323} } // namespace JSC::DFG
324
325#endif // ENABLE(DFG_JIT)
326
327#endif // DFGStructureAbstractValue_h
328
329
330