1/*
2 * Copyright (C) 2013-2018 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#include "config.h"
27#include "DFGClobberSet.h"
28
29#if ENABLE(DFG_JIT)
30
31#include "DFGClobberize.h"
32#include "JSCInlines.h"
33#include <wtf/ListDump.h>
34
35namespace JSC { namespace DFG {
36
37ClobberSet::ClobberSet() { }
38ClobberSet::~ClobberSet() { }
39
40void ClobberSet::add(AbstractHeap heap)
41{
42 HashMap<AbstractHeap, bool>::AddResult result = m_clobbers.add(heap, true);
43 if (!result.isNewEntry) {
44 if (result.iterator->value)
45 return;
46 result.iterator->value = true;
47 }
48 while (heap.kind() != World) {
49 heap = heap.supertype();
50 if (!m_clobbers.add(heap, false).isNewEntry)
51 return;
52 }
53}
54
55void ClobberSet::addAll(const ClobberSet& other)
56{
57 // If the other set has a direct heap, we make sure we have it and we set its
58 // value to be true.
59 //
60 // If the other heap has a super heap, we make sure it's present but don't
61 // modify its value - so we had it directly already then this doesn't change.
62
63 if (this == &other)
64 return;
65
66 HashMap<AbstractHeap, bool>::const_iterator iter = other.m_clobbers.begin();
67 HashMap<AbstractHeap, bool>::const_iterator end = other.m_clobbers.end();
68 for (; iter != end; ++iter)
69 m_clobbers.add(iter->key, iter->value).iterator->value |= iter->value;
70}
71
72bool ClobberSet::contains(AbstractHeap heap) const
73{
74 HashMap<AbstractHeap, bool>::const_iterator iter = m_clobbers.find(heap);
75 if (iter == m_clobbers.end())
76 return false;
77 return iter->value;
78}
79
80bool ClobberSet::overlaps(AbstractHeap heap) const
81{
82 if (m_clobbers.find(heap) != m_clobbers.end())
83 return true;
84 if (heap.kind() == DOMState && !heap.payload().isTop()) {
85 // DOMState heap has its own hierarchy. For direct heap clobbers that payload is not Top,
86 // we should query whether the clobber overlaps with the given heap.
87 DOMJIT::HeapRange range = DOMJIT::HeapRange::fromRaw(heap.payload().value32());
88 for (auto pair : m_clobbers) {
89 bool direct = pair.value;
90 if (!direct)
91 continue;
92 AbstractHeap clobber = pair.key;
93 if (clobber.kind() != DOMState)
94 continue;
95 if (clobber.payload().isTop())
96 return true;
97 if (DOMJIT::HeapRange::fromRaw(clobber.payload().value32()).overlaps(range))
98 return true;
99 }
100 }
101 while (heap.kind() != World) {
102 heap = heap.supertype();
103 if (contains(heap))
104 return true;
105 }
106 return false;
107}
108
109void ClobberSet::clear()
110{
111 m_clobbers.clear();
112}
113
114HashSet<AbstractHeap> ClobberSet::direct() const
115{
116 return setOf(true);
117}
118
119HashSet<AbstractHeap> ClobberSet::super() const
120{
121 return setOf(false);
122}
123
124void ClobberSet::dump(PrintStream& out) const
125{
126 out.print("(Direct:[", sortedListDump(direct()), "], Super:[", sortedListDump(super()), "])");
127}
128
129HashSet<AbstractHeap> ClobberSet::setOf(bool direct) const
130{
131 HashSet<AbstractHeap> result;
132 for (auto& clobber : m_clobbers) {
133 if (clobber.value == direct)
134 result.add(clobber.key);
135 }
136 return result;
137}
138
139void addReads(Graph& graph, Node* node, ClobberSet& readSet)
140{
141 ClobberSetAdd addRead(readSet);
142 NoOpClobberize noOp;
143 clobberize(graph, node, addRead, noOp, noOp);
144}
145
146void addWrites(Graph& graph, Node* node, ClobberSet& writeSet)
147{
148 NoOpClobberize noOp;
149 ClobberSetAdd addWrite(writeSet);
150 clobberize(graph, node, noOp, addWrite, noOp);
151}
152
153void addReadsAndWrites(Graph& graph, Node* node, ClobberSet& readSet, ClobberSet& writeSet)
154{
155 ClobberSetAdd addRead(readSet);
156 ClobberSetAdd addWrite(writeSet);
157 NoOpClobberize noOp;
158 clobberize(graph, node, addRead, addWrite, noOp);
159}
160
161ClobberSet writeSet(Graph& graph, Node* node)
162{
163 ClobberSet result;
164 addWrites(graph, node, result);
165 return result;
166}
167
168bool readsOverlap(Graph& graph, Node* node, ClobberSet& readSet)
169{
170 ClobberSetOverlaps addRead(readSet);
171 NoOpClobberize noOp;
172 clobberize(graph, node, addRead, noOp, noOp);
173 return addRead.result();
174}
175
176bool writesOverlap(Graph& graph, Node* node, ClobberSet& writeSet)
177{
178 NoOpClobberize noOp;
179 ClobberSetOverlaps addWrite(writeSet);
180 clobberize(graph, node, noOp, addWrite, noOp);
181 return addWrite.result();
182}
183
184} } // namespace JSC::DFG
185
186#endif // ENABLE(DFG_JIT)
187
188