2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #ifndef DFGAbstractInterpreter_h
27 #define DFGAbstractInterpreter_h
31 #include "DFGAbstractValue.h"
32 #include "DFGBranchDirection.h"
35 #include "DFGPhiChildren.h"
37 namespace JSC { namespace DFG {
39 template<typename AbstractStateType>
40 class AbstractInterpreter {
42 AbstractInterpreter(Graph&, AbstractStateType&);
43 ~AbstractInterpreter();
45 AbstractValue& forNode(Node* node)
47 return m_state.forNode(node);
50 AbstractValue& forNode(Edge edge)
52 return forNode(edge.node());
55 Operands<AbstractValue>& variables()
57 return m_state.variables();
60 bool needsTypeCheck(Node* node, SpeculatedType typesPassedThrough)
62 return !forNode(node).isType(typesPassedThrough);
65 bool needsTypeCheck(Edge edge, SpeculatedType typesPassedThrough)
67 return needsTypeCheck(edge.node(), typesPassedThrough);
70 bool needsTypeCheck(Edge edge)
72 return needsTypeCheck(edge, typeFilterFor(edge.useKind()));
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
80 // for block terminals, so long as those terminals are not Return or Unreachable.
82 // This is guaranteed to be equivalent to doing:
84 // state.startExecuting()
85 // state.executeEdges(index);
86 // result = state.executeEffects(index);
87 bool execute(unsigned indexInBlock);
90 // Indicate the start of execution of a node. It resets any state in the node
91 // that is progressively built up by executeEdges() and executeEffects().
92 void startExecuting();
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);
100 ALWAYS_INLINE void filterEdgeByUse(Edge& edge)
102 ASSERT(mayHaveTypeCheck(edge.useKind()) || !needsTypeCheck(edge));
103 filterByType(edge, typeFilterFor(edge.useKind()));
105 ALWAYS_INLINE void filterEdgeByUse(Node*, Edge& edge)
107 filterEdgeByUse(edge);
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);
113 bool executeEffects(unsigned clobberLimit, Node*);
115 void dump(PrintStream& out) const;
116 void dump(PrintStream& out);
119 FiltrationResult filter(T node, const StructureSet& set, SpeculatedType admittedTypes = SpecNone)
121 return filter(forNode(node), set, admittedTypes);
125 FiltrationResult filterArrayModes(T node, ArrayModes arrayModes)
127 return filterArrayModes(forNode(node), arrayModes);
131 FiltrationResult filter(T node, SpeculatedType type)
133 return filter(forNode(node), type);
137 FiltrationResult filterByValue(T node, FrozenValue value)
139 return filterByValue(forNode(node), value);
142 FiltrationResult filter(AbstractValue&, const StructureSet&, SpeculatedType admittedTypes = SpecNone);
143 FiltrationResult filterArrayModes(AbstractValue&, ArrayModes);
144 FiltrationResult filter(AbstractValue&, SpeculatedType);
145 FiltrationResult filterByValue(AbstractValue&, FrozenValue);
147 PhiChildren* phiChildren() { return m_phiChildren.get(); }
150 void clobberWorld(const CodeOrigin&, unsigned indexInBlock);
152 template<typename Functor>
153 void forAllValues(unsigned indexInBlock, Functor&);
155 void clobberStructures(unsigned indexInBlock);
156 void observeTransition(unsigned indexInBlock, Structure* from, Structure* to);
157 void observeTransitions(unsigned indexInBlock, const TransitionVector&);
158 void setDidClobber();
161 UnknownBooleanResult,
165 BooleanResult booleanResult(Node*, AbstractValue&);
167 void setBuiltInConstant(Node* node, FrozenValue value)
169 AbstractValue& abstractValue = forNode(node);
170 abstractValue.set(m_graph, value, m_state.structureClobberState());
171 abstractValue.fixTypeForRepresentation(m_graph, node);
174 void setConstant(Node* node, FrozenValue value)
176 setBuiltInConstant(node, value);
177 m_state.setFoundConstants(true);
180 ALWAYS_INLINE void filterByType(Edge& edge, SpeculatedType type)
182 AbstractValue& value = forNode(edge);
183 if (!value.isType(type))
184 edge.setProofStatus(NeedsCheck);
186 edge.setProofStatus(IsProved);
191 void verifyEdge(Node*, Edge);
192 void verifyEdges(Node*);
194 CodeBlock* m_codeBlock;
196 AbstractStateType& m_state;
197 std::unique_ptr<PhiChildren> m_phiChildren;
200 } } // namespace JSC::DFG
202 #endif // ENABLE(DFG_JIT)
204 #endif // DFGAbstractInterpreter_h