1/*
2 * Copyright (C) 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#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    while (heap.kind() != World) {
85        heap = heap.supertype();
86        if (contains(heap))
87            return true;
88    }
89    return false;
90}
91
92void ClobberSet::clear()
93{
94    m_clobbers.clear();
95}
96
97HashSet<AbstractHeap> ClobberSet::direct() const
98{
99    return setOf(true);
100}
101
102HashSet<AbstractHeap> ClobberSet::super() const
103{
104    return setOf(false);
105}
106
107void ClobberSet::dump(PrintStream& out) const
108{
109    out.print("(Direct:[", sortedListDump(direct()), "], Super:[", sortedListDump(super()), "])");
110}
111
112HashSet<AbstractHeap> ClobberSet::setOf(bool direct) const
113{
114    HashSet<AbstractHeap> result;
115    for (HashMap<AbstractHeap, bool>::const_iterator iter = m_clobbers.begin(); iter != m_clobbers.end(); ++iter) {
116        if (iter->value == direct)
117            result.add(iter->key);
118    }
119    return result;
120}
121
122void addReads(Graph& graph, Node* node, ClobberSet& readSet)
123{
124    ClobberSetAdd addRead(readSet);
125    NoOpClobberize addWrite;
126    clobberize(graph, node, addRead, addWrite);
127}
128
129void addWrites(Graph& graph, Node* node, ClobberSet& writeSet)
130{
131    NoOpClobberize addRead;
132    ClobberSetAdd addWrite(writeSet);
133    clobberize(graph, node, addRead, addWrite);
134}
135
136void addReadsAndWrites(Graph& graph, Node* node, ClobberSet& readSet, ClobberSet& writeSet)
137{
138    ClobberSetAdd addRead(readSet);
139    ClobberSetAdd addWrite(writeSet);
140    clobberize(graph, node, addRead, addWrite);
141}
142
143bool readsOverlap(Graph& graph, Node* node, ClobberSet& readSet)
144{
145    ClobberSetOverlaps addRead(readSet);
146    NoOpClobberize addWrite;
147    clobberize(graph, node, addRead, addWrite);
148    return addRead.result();
149}
150
151bool writesOverlap(Graph& graph, Node* node, ClobberSet& writeSet)
152{
153    NoOpClobberize addRead;
154    ClobberSetOverlaps addWrite(writeSet);
155    clobberize(graph, node, addRead, addWrite);
156    return addWrite.result();
157}
158
159} } // namespace JSC::DFG
160
161#endif // ENABLE(DFG_JIT)
162
163