blob: bbc38c1d92245578b18ade809c938cf21ed1c77e [file] [log] [blame]
oliver@apple.com55d32d92013-07-25 04:05:03 +00001/*
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00002 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
oliver@apple.com55d32d92013-07-25 04:05:03 +00003 *
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#ifndef DFGAbstractInterpreter_h
27#define DFGAbstractInterpreter_h
28
oliver@apple.com55d32d92013-07-25 04:05:03 +000029#if ENABLE(DFG_JIT)
30
fpizlo@apple.com0bef2a12014-02-10 19:26:29 +000031#include "DFGAbstractValue.h"
32#include "DFGBranchDirection.h"
oliver@apple.com55d32d92013-07-25 04:05:03 +000033#include "DFGGraph.h"
fpizlo@apple.com0bef2a12014-02-10 19:26:29 +000034#include "DFGNode.h"
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000035#include "DFGPhiChildren.h"
oliver@apple.com55d32d92013-07-25 04:05:03 +000036
37namespace JSC { namespace DFG {
38
39template<typename AbstractStateType>
40class AbstractInterpreter {
41public:
commit-queue@webkit.org8f097f72014-05-19 09:00:56 +000042 AbstractInterpreter(Graph&, AbstractStateType&);
oliver@apple.com55d32d92013-07-25 04:05:03 +000043 ~AbstractInterpreter();
44
45 AbstractValue& forNode(Node* node)
46 {
47 return m_state.forNode(node);
48 }
49
50 AbstractValue& forNode(Edge edge)
51 {
52 return forNode(edge.node());
53 }
54
55 Operands<AbstractValue>& variables()
56 {
57 return m_state.variables();
58 }
59
60 bool needsTypeCheck(Node* node, SpeculatedType typesPassedThrough)
61 {
fpizlo@apple.com6921b292013-09-18 17:14:02 +000062 return !forNode(node).isType(typesPassedThrough);
oliver@apple.com55d32d92013-07-25 04:05:03 +000063 }
64
65 bool needsTypeCheck(Edge edge, SpeculatedType typesPassedThrough)
66 {
67 return needsTypeCheck(edge.node(), typesPassedThrough);
68 }
69
70 bool needsTypeCheck(Edge edge)
71 {
72 return needsTypeCheck(edge, typeFilterFor(edge.useKind()));
73 }
74
75 // Abstractly executes the given node. The new abstract state is stored into an
76 // abstract stack stored in *this. Loads of local variables (that span
77 // basic blocks) interrogate the basic block's notion of the state at the head.
78 // Stores to local variables are handled in endBasicBlock(). This returns true
79 // if execution should continue past this node. Notably, it will return true
oliver@apple.com1fc04182013-08-19 19:40:13 +000080 // for block terminals, so long as those terminals are not Return or Unreachable.
oliver@apple.com55d32d92013-07-25 04:05:03 +000081 //
82 // This is guaranteed to be equivalent to doing:
83 //
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000084 // state.startExecuting()
85 // state.executeEdges(index);
86 // result = state.executeEffects(index);
oliver@apple.com55d32d92013-07-25 04:05:03 +000087 bool execute(unsigned indexInBlock);
oliver@apple.come17632e2013-07-25 04:05:31 +000088 bool execute(Node*);
oliver@apple.com55d32d92013-07-25 04:05:03 +000089
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000090 // Indicate the start of execution of a node. It resets any state in the node
fpizlo@apple.comb41e6822014-07-25 20:55:17 +000091 // that is progressively built up by executeEdges() and executeEffects().
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000092 void startExecuting();
oliver@apple.com55d32d92013-07-25 04:05:03 +000093
94 // Abstractly execute the edges of the given node. This runs filterEdgeByUse()
95 // on all edges of the node. You can skip this step, if you have already used
96 // filterEdgeByUse() (or some equivalent) on each edge.
97 void executeEdges(Node*);
98 void executeEdges(unsigned indexInBlock);
99
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000100 ALWAYS_INLINE void filterEdgeByUse(Edge& edge)
oliver@apple.com55d32d92013-07-25 04:05:03 +0000101 {
102 ASSERT(mayHaveTypeCheck(edge.useKind()) || !needsTypeCheck(edge));
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000103 filterByType(edge, typeFilterFor(edge.useKind()));
104 }
105 ALWAYS_INLINE void filterEdgeByUse(Node*, Edge& edge)
106 {
107 filterEdgeByUse(edge);
oliver@apple.com55d32d92013-07-25 04:05:03 +0000108 }
109
110 // Abstractly execute the effects of the given node. This changes the abstract
111 // state assuming that edges have already been filtered.
112 bool executeEffects(unsigned indexInBlock);
oliver@apple.come17632e2013-07-25 04:05:31 +0000113 bool executeEffects(unsigned clobberLimit, Node*);
oliver@apple.com55d32d92013-07-25 04:05:03 +0000114
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +0000115 void dump(PrintStream& out) const;
oliver@apple.com55d32d92013-07-25 04:05:03 +0000116 void dump(PrintStream& out);
117
118 template<typename T>
119 FiltrationResult filter(T node, const StructureSet& set)
120 {
121 return filter(forNode(node), set);
122 }
123
124 template<typename T>
125 FiltrationResult filterArrayModes(T node, ArrayModes arrayModes)
126 {
127 return filterArrayModes(forNode(node), arrayModes);
128 }
129
130 template<typename T>
131 FiltrationResult filter(T node, SpeculatedType type)
132 {
133 return filter(forNode(node), type);
134 }
135
136 template<typename T>
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000137 FiltrationResult filterByValue(T node, FrozenValue value)
oliver@apple.com55d32d92013-07-25 04:05:03 +0000138 {
139 return filterByValue(forNode(node), value);
140 }
141
142 FiltrationResult filter(AbstractValue&, const StructureSet&);
143 FiltrationResult filterArrayModes(AbstractValue&, ArrayModes);
144 FiltrationResult filter(AbstractValue&, SpeculatedType);
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000145 FiltrationResult filterByValue(AbstractValue&, FrozenValue);
oliver@apple.com55d32d92013-07-25 04:05:03 +0000146
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +0000147 PhiChildren* phiChildren() { return m_phiChildren.get(); }
148
oliver@apple.com55d32d92013-07-25 04:05:03 +0000149private:
150 void clobberWorld(const CodeOrigin&, unsigned indexInBlock);
151 void clobberCapturedVars(const CodeOrigin&);
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +0000152
153 template<typename Functor>
154 void forAllValues(unsigned indexInBlock, Functor&);
155
oliver@apple.com55d32d92013-07-25 04:05:03 +0000156 void clobberStructures(unsigned indexInBlock);
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +0000157 void observeTransition(unsigned indexInBlock, Structure* from, Structure* to);
158 void observeTransitions(unsigned indexInBlock, const TransitionVector&);
159 void setDidClobber();
oliver@apple.com55d32d92013-07-25 04:05:03 +0000160
161 enum BooleanResult {
162 UnknownBooleanResult,
163 DefinitelyFalse,
164 DefinitelyTrue
165 };
166 BooleanResult booleanResult(Node*, AbstractValue&);
167
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000168 void setBuiltInConstant(Node* node, FrozenValue value)
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000169 {
170 AbstractValue& abstractValue = forNode(node);
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +0000171 abstractValue.set(m_graph, value, m_state.structureClobberState());
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000172 abstractValue.fixTypeForRepresentation(node);
173 }
174
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000175 void setConstant(Node* node, FrozenValue value)
oliver@apple.com55d32d92013-07-25 04:05:03 +0000176 {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000177 setBuiltInConstant(node, value);
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000178 m_state.setFoundConstants(true);
oliver@apple.com55d32d92013-07-25 04:05:03 +0000179 }
180
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000181 ALWAYS_INLINE void filterByType(Edge& edge, SpeculatedType type)
oliver@apple.com55d32d92013-07-25 04:05:03 +0000182 {
183 AbstractValue& value = forNode(edge);
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000184 if (!value.isType(type))
oliver@apple.com55d32d92013-07-25 04:05:03 +0000185 edge.setProofStatus(NeedsCheck);
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000186 else
oliver@apple.com55d32d92013-07-25 04:05:03 +0000187 edge.setProofStatus(IsProved);
188
189 filter(value, type);
190 }
191
192 void verifyEdge(Node*, Edge);
193 void verifyEdges(Node*);
194
195 CodeBlock* m_codeBlock;
196 Graph& m_graph;
197 AbstractStateType& m_state;
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +0000198 std::unique_ptr<PhiChildren> m_phiChildren;
oliver@apple.com55d32d92013-07-25 04:05:03 +0000199};
200
201} } // namespace JSC::DFG
202
203#endif // ENABLE(DFG_JIT)
204
205#endif // DFGAbstractInterpreter_h
206