Record the HashSet/HashMap operations in DFG/FTL/B3 and replay them in a benchmark
[WebKit-https.git] / Source / WTF / wtf / LoggingHashMap.h
1 /*
2  * Copyright (C) 2017 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 #pragma once
27
28 #include <wtf/DataLog.h>
29 #include <wtf/HashMap.h>
30 #include <wtf/LoggingHashID.h>
31 #include <wtf/LoggingHashTraits.h>
32
33 namespace WTF {
34
35 template<
36     const char* typeArguments,
37     typename KeyArg, typename MappedArg, typename HashArg = typename DefaultHash<KeyArg>::Hash,
38     typename KeyTraitsArg = HashTraits<KeyArg>, typename MappedTraitsArg = HashTraits<MappedArg>,
39     typename LoggingKeyTraits = LoggingHashKeyTraits<KeyArg>,
40     typename LoggingValueTraits = LoggingHashValueTraits<MappedArg>>
41 class LoggingHashMap final {
42     WTF_MAKE_FAST_ALLOCATED;
43
44 public:
45     typedef WTF::HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> HashMap;
46     
47     typedef typename HashMap::KeyType KeyType;
48     typedef typename HashMap::MappedType MappedType;
49     typedef typename HashMap::KeyValuePairType KeyValuePairType;
50     
51     typedef typename HashMap::iterator iterator;
52     typedef typename HashMap::const_iterator const_iterator;
53     typedef typename HashMap::AddResult AddResult;
54
55     LoggingHashMap()
56     {
57         dataLog("auto* ", m_id, " = new HashMap<", typeArguments, ">();\n");
58     }
59     
60     ~LoggingHashMap()
61     {
62         dataLog("delete ", m_id, ";\n");
63     }
64     
65     LoggingHashMap(const LoggingHashMap& other)
66         : m_map(other.m_map)
67     {
68         dataLog("auto* ", m_id, " = new HashMap(*", other.m_id, ");");
69     }
70     
71     LoggingHashMap(LoggingHashMap&& other)
72         : m_map(other.m_map)
73     {
74         dataLog("auto* ", m_id, " = new HashMap(WTFMove(*", other.m_id, "));");
75     }
76     
77     LoggingHashMap& operator=(const LoggingHashMap& other)
78     {
79         dataLog("*", m_id, " = *", other.m_id, ";\n");
80         m_map = other.m_map;
81     }
82     
83     LoggingHashMap& operator=(LoggingHashMap&& other)
84     {
85         dataLog("*", m_id, " = WTFMove(*", other.m_id, ");\n");
86         m_map = WTFMove(other.m_map);
87     }
88     
89     void swap(LoggingHashMap& other)
90     {
91         dataLog(m_id, "->swap(*", RawPointer(&other), ");\n");
92         m_map.swap(other.m_map);
93     }
94     
95     // A bunch of stuff does not get logged.
96     unsigned size() const { return m_map.size(); }
97     unsigned capacity() const { return m_map.capacity(); }
98     bool isEmpty() const { return m_map.isEmpty(); }
99     
100     iterator begin() { return m_map.begin(); }
101     iterator end() { return m_map.end(); }
102     const_iterator begin() const { return m_map.begin(); }
103     const_iterator end() const { return m_map.end(); }
104     
105     auto keys() { return m_map.keys(); }
106     const auto keys() const { return m_map.keys(); }
107     auto values() { return m_map.values(); }
108     const auto values() const { return m_map.values(); }
109     
110     iterator find(const KeyType& key)
111     {
112         StringPrintStream string;
113         string.print("{\n");
114         string.print("    auto iter = ", m_id, "->find(");
115         LoggingKeyTraits::print(string, key);
116         string.print(");\n");
117         iterator result = m_map.find(key);
118         if (result == m_map.end())
119             string.print("    RELEASE_ASSERT(iter == ", m_id, "->end());\n");
120         else
121             string.print("    RELEASE_ASSERT(iter != ", m_id, "->end());\n");
122         string.print("}\n");
123         dataLog(string.toCString());
124         return result;
125     }
126     
127     const_iterator find(const KeyType& key) const
128     {
129         StringPrintStream string;
130         string.print("{\n");
131         string.print("    auto iter = ", m_id, "->find(");
132         LoggingKeyTraits::print(string, key);
133         string.print(");\n");
134         const_iterator result = m_map.find(key);
135         if (result == m_map.end())
136             string.print("    RELEASE_ASSERT(iter == ", m_id, "->end());\n");
137         else
138             string.print("    RELEASE_ASSERT(iter != ", m_id, "->end());\n");
139         string.print("}\n");
140         dataLog(string.toCString());
141         return result;
142     }
143     
144     bool contains(const KeyType& key) const
145     {
146         return find(key) != end();
147     }
148     
149     MappedPeekType get(const KeyType& key) const
150     {
151         find(key);
152         return m_map.get(key);
153     }
154     
155     MappedPeekType fastGet(const KeyType& key) const
156     {
157         find(key);
158         return m_map.fastGet(key);
159     }
160     
161     template<typename PassedType>
162     AddResult set(const KeyType& key, PassedType&& passedValue)
163     {
164         StringPrintStream string;
165         string.print(m_id, "->set(");
166         LoggingKeyTraits::print(string, key);
167         string.print(", ");
168         LoggingValueTraits::print(string, passedValue);
169         string.print(");\n");
170         dataLog(string.toCString());
171         return set(key, std::forward<PassedType>(passedValue));
172     }
173     
174     template<typename PassedType>
175     AddResult set(KeyType&& key, PassedType&& passedValue)
176     {
177         StringPrintStream string;
178         string.print(m_id, "->set(");
179         LoggingKeyTraits::print(string, key);
180         string.print(", ");
181         LoggingValueTraits::print(string, passedValue);
182         string.print(");\n");
183         dataLog(string.toCString());
184         return set(WTFMove(key), std::forward<PassedType>(passedValue));
185     }
186     
187     template<typename PassedType>
188     AddResult add(const KeyType& key, PassedType&& passedValue)
189     {
190         StringPrintStream string;
191         string.print(m_id, "->add(");
192         LoggingKeyTraits::print(string, key);
193         string.print(", ");
194         LoggingValueTraits::print(string, passedValue);
195         string.print(");\n");
196         dataLog(string.toCString());
197         return add(key, std::forward<PassedType>(passedValue));
198     }
199     
200     template<typename PassedType>
201     AddResult add(KeyType&& key, PassedType&& passedValue)
202     {
203         StringPrintStream string;
204         string.print(m_id, "->add(");
205         LoggingKeyTraits::print(string, key);
206         string.print(", ");
207         LoggingValueTraits::print(string, passedValue);
208         string.print(");\n");
209         dataLog(string.toCString());
210         return add(WTFMove(key), std::forward<PassedType>(passedValue));
211     }
212     
213     template<typename PassedType>
214     AddResult fastAdd(const KeyType& key, PassedType&& passedValue)
215     {
216         return add(key, std::forward<PassedType>(passedValue));
217     }
218     
219     template<typename PassedType>
220     AddResult fastAdd(KeyType&& key, PassedType&& passedValue)
221     {
222         return add(WTFMove(key), std::forward<PassedType>(passedValue));
223     }
224     
225     template<typename Func>
226     AddResult ensure(const KeyType& key, Func&& func)
227     {
228         StringPrintStream string;
229         string.print(m_id, "->ensure(");
230         LoggingKeyTraits::print(string, key);
231         string.print(", ");
232         string.print("[] () { return ");
233         bool didCallFunctor = false;
234         auto result = m_map.ensure(
235             key,
236             [&] () {
237                 didCallFunctor = true;
238                 auto result = func();
239                 LoggingValueTraits::print(string, result);
240                 return result;
241             });
242         if (!didCallFunctor)
243             LoggingValueTraits::print(string, MappedTraitsArg::emptyValue());
244         string.print("; });\n");
245         dataLog(string.toCString());
246         return result;
247     }
248     
249     template<typename Func>
250     AddResult ensure(KeyType&& key, Func&& func)
251     {
252         StringPrintStream string;
253         string.print(m_id, "->ensure(");
254         LoggingKeyTraits::print(string, key);
255         string.print(", ");
256         string.print("[] () { return ");
257         bool didCallFunctor = false;
258         auto result = m_map.ensure(
259             WTFMove(key),
260             [&] () {
261                 didCallFunctor = true;
262                 auto result = func();
263                 LoggingValueTraits::print(string, result);
264                 return result;
265             });
266         if (!didCallFunctor)
267             LoggingValueTraits::print(string, MappedTraitsArg::emptyValue());
268         string.print("; });\n");
269         dataLog(string.toCString());
270         return result;
271     }
272     
273     bool remove(const KeyType& key)
274     {
275         StringPrintStream string;
276         string.print(m_id, "->remove(");
277         LoggingKeyTraits::print(string, key);
278         string.print(");\n");
279         dataLog(string.toCString());
280         return m_map.remove(key);
281     }
282     
283     bool remove(iterator iter)
284     {
285         // FIXME: It would be nice if we could do better than this.
286         if (iter == end())
287             return false;
288         return remove(iter->key);
289     }
290
291     // FIXME: Implement removeIf().
292     
293     void clear()
294     {
295         dataLog(m_id, "->clear();\n");
296         m_map.clear();
297     }
298     
299     // FIXME: Implement the no-convert overloads.
300     
301 private:
302     HashMap m_map;
303     LoggingHashID m_id;
304 };
305
306 } // namespace WTF
307
308 using WTF::LoggingHashMap;