We should support CreateThis in the FTL
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGDesiredWatchpoints.h
1 /*
2  * Copyright (C) 2013-2015 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 #if ENABLE(DFG_JIT)
29
30 #include "DFGCommonData.h"
31 #include "DFGDesiredInferredType.h"
32 #include "InferredValue.h"
33 #include "JSArrayBufferView.h"
34 #include "ObjectPropertyCondition.h"
35 #include "Watchpoint.h"
36 #include <wtf/CommaPrinter.h>
37 #include <wtf/HashSet.h>
38
39 namespace JSC { namespace DFG {
40
41 class Graph;
42
43 template<typename T>
44 struct SetPointerAdaptor {
45     static void add(CodeBlock* codeBlock, T set, CommonData& common)
46     {
47         return set->add(common.watchpoints.add(codeBlock));
48     }
49     static bool hasBeenInvalidated(T set)
50     {
51         return set->hasBeenInvalidated();
52     }
53     static void dumpInContext(PrintStream& out, T set, DumpContext*)
54     {
55         out.print(RawPointer(set));
56     }
57 };
58
59 struct InferredValueAdaptor {
60     static void add(CodeBlock*, InferredValue*, CommonData&);
61     static bool hasBeenInvalidated(InferredValue* inferredValue)
62     {
63         return inferredValue->hasBeenInvalidated();
64     }
65     static void dumpInContext(PrintStream& out, InferredValue* inferredValue, DumpContext*)
66     {
67         out.print(RawPointer(inferredValue));
68     }
69 };
70
71 struct ArrayBufferViewWatchpointAdaptor {
72     static void add(CodeBlock*, JSArrayBufferView*, CommonData&);
73     static bool hasBeenInvalidated(JSArrayBufferView* view)
74     {
75         return !view->length();
76     }
77     static void dumpInContext(PrintStream& out, JSArrayBufferView* view, DumpContext* context)
78     {
79         out.print(inContext(JSValue(view), context));
80     }
81 };
82
83 struct AdaptiveStructureWatchpointAdaptor {
84     static void add(CodeBlock*, const ObjectPropertyCondition&, CommonData&);
85     static bool hasBeenInvalidated(const ObjectPropertyCondition& key)
86     {
87         return !key.isWatchable();
88     }
89     static void dumpInContext(
90         PrintStream& out, const ObjectPropertyCondition& key, DumpContext* context)
91     {
92         out.print(inContext(key, context));
93     }
94 };
95
96 struct InferredTypeAdaptor {
97     static void add(CodeBlock*, const DesiredInferredType&, CommonData&);
98     static bool hasBeenInvalidated(const DesiredInferredType& key)
99     {
100         return !key.isStillValid();
101     }
102     static void dumpInContext(PrintStream& out, const DesiredInferredType& key, DumpContext* context)
103     {
104         out.print(inContext(key, context));
105     }
106 };
107
108 template<typename WatchpointSetType, typename Adaptor = SetPointerAdaptor<WatchpointSetType>>
109 class GenericDesiredWatchpoints {
110 #if !ASSERT_DISABLED
111     typedef HashMap<WatchpointSetType, bool> StateMap;
112 #endif
113 public:
114     GenericDesiredWatchpoints()
115         : m_reallyAdded(false)
116     {
117     }
118     
119     void addLazily(const WatchpointSetType& set)
120     {
121         m_sets.add(set);
122     }
123     
124     void reallyAdd(CodeBlock* codeBlock, CommonData& common)
125     {
126         RELEASE_ASSERT(!m_reallyAdded);
127         
128         for (auto& set : m_sets)
129             Adaptor::add(codeBlock, set, common);
130         
131         m_reallyAdded = true;
132     }
133     
134     bool areStillValid() const
135     {
136         for (auto& set : m_sets) {
137             if (Adaptor::hasBeenInvalidated(set))
138                 return false;
139         }
140         
141         return true;
142     }
143     
144     bool isWatched(const WatchpointSetType& set) const
145     {
146         return m_sets.contains(set);
147     }
148
149     void dumpInContext(PrintStream& out, DumpContext* context) const
150     {
151         CommaPrinter comma;
152         for (const WatchpointSetType& entry : m_sets) {
153             out.print(comma);
154             Adaptor::dumpInContext(out, entry, context);
155         }
156     }
157
158 private:
159     HashSet<WatchpointSetType> m_sets;
160     bool m_reallyAdded;
161 };
162
163 class DesiredWatchpoints {
164 public:
165     DesiredWatchpoints();
166     ~DesiredWatchpoints();
167     
168     void addLazily(WatchpointSet*);
169     void addLazily(InlineWatchpointSet&);
170     void addLazily(InferredValue*);
171     void addLazily(JSArrayBufferView*);
172     
173     // It's recommended that you don't call this directly. Use Graph::watchCondition(), which does
174     // the required GC magic as well as some other bookkeeping.
175     void addLazily(const ObjectPropertyCondition&);
176
177     // It's recommended that you don't call this directly. Use Graph::inferredTypeFor(), which does
178     // the required GC magic.
179     void addLazily(const DesiredInferredType&);
180     
181     bool consider(Structure*);
182     
183     void reallyAdd(CodeBlock*, CommonData&);
184     
185     bool areStillValid() const;
186     
187     bool isWatched(WatchpointSet* set)
188     {
189         return m_sets.isWatched(set);
190     }
191     bool isWatched(InlineWatchpointSet& set)
192     {
193         return m_inlineSets.isWatched(&set);
194     }
195     bool isWatched(InferredValue* inferredValue)
196     {
197         return m_inferredValues.isWatched(inferredValue);
198     }
199     bool isWatched(JSArrayBufferView* view)
200     {
201         return m_bufferViews.isWatched(view);
202     }
203     bool isWatched(const ObjectPropertyCondition& key)
204     {
205         return m_adaptiveStructureSets.isWatched(key);
206     }
207     bool isWatched(const DesiredInferredType& key)
208     {
209         return m_inferredTypes.isWatched(key);
210     }
211
212     void dumpInContext(PrintStream&, DumpContext*) const;
213     void dump(PrintStream&) const;
214     
215 private:
216     GenericDesiredWatchpoints<WatchpointSet*> m_sets;
217     GenericDesiredWatchpoints<InlineWatchpointSet*> m_inlineSets;
218     GenericDesiredWatchpoints<InferredValue*, InferredValueAdaptor> m_inferredValues;
219     GenericDesiredWatchpoints<JSArrayBufferView*, ArrayBufferViewWatchpointAdaptor> m_bufferViews;
220     GenericDesiredWatchpoints<ObjectPropertyCondition, AdaptiveStructureWatchpointAdaptor> m_adaptiveStructureSets;
221     GenericDesiredWatchpoints<DesiredInferredType, InferredTypeAdaptor> m_inferredTypes;
222 };
223
224 } } // namespace JSC::DFG
225
226 #endif // ENABLE(DFG_JIT)