[BigInt] Add ValueBitLShift into DFG
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGAbstractInterpreter.h
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 #pragma once
27
28 #if ENABLE(DFG_JIT)
29
30 #include "DFGAbstractValue.h"
31 #include "DFGGraph.h"
32 #include "DFGNode.h"
33 #include "DFGNodeFlowProjection.h"
34 #include "DFGPhiChildren.h"
35
36 namespace JSC { namespace DFG {
37
38 template<typename AbstractStateType>
39 class AbstractInterpreter {
40 public:
41     AbstractInterpreter(Graph&, AbstractStateType&);
42     ~AbstractInterpreter();
43     
44     ALWAYS_INLINE AbstractValue& forNode(NodeFlowProjection node)
45     {
46         return m_state.forNode(node);
47     }
48     
49     ALWAYS_INLINE AbstractValue& forNode(Edge edge)
50     {
51         return forNode(edge.node());
52     }
53     
54     ALWAYS_INLINE void clearForNode(NodeFlowProjection node)
55     {
56         m_state.clearForNode(node);
57     }
58     
59     ALWAYS_INLINE void clearForNode(Edge edge)
60     {
61         clearForNode(edge.node());
62     }
63
64     template<typename... Arguments>
65     ALWAYS_INLINE void setForNode(NodeFlowProjection node, Arguments&&... arguments)
66     {
67         m_state.setForNode(node, std::forward<Arguments>(arguments)...);
68     }
69
70     template<typename... Arguments>
71     ALWAYS_INLINE void setForNode(Edge edge, Arguments&&... arguments)
72     {
73         setForNode(edge.node(), std::forward<Arguments>(arguments)...);
74     }
75
76     template<typename... Arguments>
77     ALWAYS_INLINE void setTypeForNode(NodeFlowProjection node, Arguments&&... arguments)
78     {
79         m_state.setTypeForNode(node, std::forward<Arguments>(arguments)...);
80     }
81
82     template<typename... Arguments>
83     ALWAYS_INLINE void setTypeForNode(Edge edge, Arguments&&... arguments)
84     {
85         setTypeForNode(edge.node(), std::forward<Arguments>(arguments)...);
86     }
87     
88     template<typename... Arguments>
89     ALWAYS_INLINE void setNonCellTypeForNode(NodeFlowProjection node, Arguments&&... arguments)
90     {
91         m_state.setNonCellTypeForNode(node, std::forward<Arguments>(arguments)...);
92     }
93
94     template<typename... Arguments>
95     ALWAYS_INLINE void setNonCellTypeForNode(Edge edge, Arguments&&... arguments)
96     {
97         setNonCellTypeForNode(edge.node(), std::forward<Arguments>(arguments)...);
98     }
99     
100     ALWAYS_INLINE void makeBytecodeTopForNode(NodeFlowProjection node)
101     {
102         m_state.makeBytecodeTopForNode(node);
103     }
104     
105     ALWAYS_INLINE void makeBytecodeTopForNode(Edge edge)
106     {
107         makeBytecodeTopForNode(edge.node());
108     }
109     
110     ALWAYS_INLINE void makeHeapTopForNode(NodeFlowProjection node)
111     {
112         m_state.makeHeapTopForNode(node);
113     }
114     
115     ALWAYS_INLINE void makeHeapTopForNode(Edge edge)
116     {
117         makeHeapTopForNode(edge.node());
118     }
119     
120     bool needsTypeCheck(Node* node, SpeculatedType typesPassedThrough)
121     {
122         return !forNode(node).isType(typesPassedThrough);
123     }
124     
125     bool needsTypeCheck(Edge edge, SpeculatedType typesPassedThrough)
126     {
127         return needsTypeCheck(edge.node(), typesPassedThrough);
128     }
129     
130     bool needsTypeCheck(Edge edge)
131     {
132         return needsTypeCheck(edge, typeFilterFor(edge.useKind()));
133     }
134     
135     // Abstractly executes the given node. The new abstract state is stored into an
136     // abstract stack stored in *this. Loads of local variables (that span
137     // basic blocks) interrogate the basic block's notion of the state at the head.
138     // Stores to local variables are handled in endBasicBlock(). This returns true
139     // if execution should continue past this node. Notably, it will return true
140     // for block terminals, so long as those terminals are not Return or Unreachable.
141     //
142     // This is guaranteed to be equivalent to doing:
143     //
144     // state.startExecuting()
145     // state.executeEdges(node);
146     // result = state.executeEffects(index);
147     bool execute(unsigned indexInBlock);
148     bool execute(Node*);
149     
150     // Indicate the start of execution of a node. It resets any state in the node
151     // that is progressively built up by executeEdges() and executeEffects().
152     void startExecuting();
153     
154     // Abstractly execute the edges of the given node. This runs filterEdgeByUse()
155     // on all edges of the node. You can skip this step, if you have already used
156     // filterEdgeByUse() (or some equivalent) on each edge.
157     void executeEdges(Node*);
158
159     void executeKnownEdgeTypes(Node*);
160     
161     ALWAYS_INLINE void filterEdgeByUse(Edge& edge)
162     {
163         UseKind useKind = edge.useKind();
164         if (useKind == UntypedUse)
165             return;
166         filterByType(edge, typeFilterFor(useKind));
167     }
168     
169     // Abstractly execute the effects of the given node. This changes the abstract
170     // state assuming that edges have already been filtered.
171     bool executeEffects(unsigned indexInBlock);
172     bool executeEffects(unsigned clobberLimit, Node*);
173     
174     void dump(PrintStream& out) const;
175     void dump(PrintStream& out);
176     
177     template<typename T>
178     FiltrationResult filter(T node, const RegisteredStructureSet& set, SpeculatedType admittedTypes = SpecNone)
179     {
180         return filter(forNode(node), set, admittedTypes);
181     }
182     
183     template<typename T>
184     FiltrationResult filterArrayModes(T node, ArrayModes arrayModes)
185     {
186         return filterArrayModes(forNode(node), arrayModes);
187     }
188     
189     template<typename T>
190     FiltrationResult filter(T node, SpeculatedType type)
191     {
192         return filter(forNode(node), type);
193     }
194     
195     template<typename T>
196     FiltrationResult filterByValue(T node, FrozenValue value)
197     {
198         return filterByValue(forNode(node), value);
199     }
200     
201     template<typename T>
202     FiltrationResult filterClassInfo(T node, const ClassInfo* classInfo)
203     {
204         return filterClassInfo(forNode(node), classInfo);
205     }
206
207     FiltrationResult filter(AbstractValue&, const RegisteredStructureSet&, SpeculatedType admittedTypes = SpecNone);
208     FiltrationResult filterArrayModes(AbstractValue&, ArrayModes);
209     FiltrationResult filter(AbstractValue&, SpeculatedType);
210     FiltrationResult filterByValue(AbstractValue&, FrozenValue);
211     FiltrationResult filterClassInfo(AbstractValue&, const ClassInfo*);
212     
213     PhiChildren* phiChildren() { return m_phiChildren.get(); }
214     
215     void filterICStatus(Node*);
216     
217 private:
218     void clobberWorld();
219     void didFoldClobberWorld();
220     
221     bool handleConstantBinaryBitwiseOp(Node*);
222
223     template<typename Functor>
224     void forAllValues(unsigned indexInBlock, Functor&);
225     
226     void clobberStructures();
227     void didFoldClobberStructures();
228     
229     void observeTransition(unsigned indexInBlock, RegisteredStructure from, RegisteredStructure to);
230     void observeTransitions(unsigned indexInBlock, const TransitionVector&);
231     
232     enum BooleanResult {
233         UnknownBooleanResult,
234         DefinitelyFalse,
235         DefinitelyTrue
236     };
237     BooleanResult booleanResult(Node*, AbstractValue&);
238     
239     void setBuiltInConstant(Node* node, FrozenValue value)
240     {
241         AbstractValue& abstractValue = forNode(node);
242         abstractValue.set(m_graph, value, m_state.structureClobberState());
243         abstractValue.fixTypeForRepresentation(m_graph, node);
244     }
245     
246     void setConstant(Node* node, FrozenValue value)
247     {
248         setBuiltInConstant(node, value);
249         m_state.setFoundConstants(true);
250     }
251     
252     ALWAYS_INLINE void filterByType(Edge& edge, SpeculatedType type);
253     
254     void verifyEdge(Node*, Edge);
255     void verifyEdges(Node*);
256     void executeDoubleUnaryOpEffects(Node*, double(*equivalentFunction)(double));
257     
258     bool handleConstantDivOp(Node*);
259
260     CodeBlock* m_codeBlock;
261     Graph& m_graph;
262     VM& m_vm;
263     AbstractStateType& m_state;
264     std::unique_ptr<PhiChildren> m_phiChildren;
265 };
266
267 } } // namespace JSC::DFG
268
269 #endif // ENABLE(DFG_JIT)