2 * Copyright (C) 2013-2016 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 void executeKnownEdgeTypes(Node*);
102 ALWAYS_INLINE void filterEdgeByUse(Edge& edge)
104 filterByType(edge, typeFilterFor(edge.useKind()));
107 // Abstractly execute the effects of the given node. This changes the abstract
108 // state assuming that edges have already been filtered.
109 bool executeEffects(unsigned indexInBlock);
110 bool executeEffects(unsigned clobberLimit, Node*);
112 void dump(PrintStream& out) const;
113 void dump(PrintStream& out);
116 FiltrationResult filter(T node, const StructureSet& set, SpeculatedType admittedTypes = SpecNone)
118 return filter(forNode(node), set, admittedTypes);
122 FiltrationResult filterArrayModes(T node, ArrayModes arrayModes)
124 return filterArrayModes(forNode(node), arrayModes);
128 FiltrationResult filter(T node, SpeculatedType type)
130 return filter(forNode(node), type);
134 FiltrationResult filterByValue(T node, FrozenValue value)
136 return filterByValue(forNode(node), value);
139 FiltrationResult filter(AbstractValue&, const StructureSet&, SpeculatedType admittedTypes = SpecNone);
140 FiltrationResult filterArrayModes(AbstractValue&, ArrayModes);
141 FiltrationResult filter(AbstractValue&, SpeculatedType);
142 FiltrationResult filterByValue(AbstractValue&, FrozenValue);
144 PhiChildren* phiChildren() { return m_phiChildren.get(); }
147 void clobberWorld(const CodeOrigin&, unsigned indexInBlock);
149 template<typename Functor>
150 void forAllValues(unsigned indexInBlock, Functor&);
152 void clobberStructures(unsigned indexInBlock);
153 void observeTransition(unsigned indexInBlock, Structure* from, Structure* to);
154 void observeTransitions(unsigned indexInBlock, const TransitionVector&);
155 void setDidClobber();
158 UnknownBooleanResult,
162 BooleanResult booleanResult(Node*, AbstractValue&);
164 void setBuiltInConstant(Node* node, FrozenValue value)
166 AbstractValue& abstractValue = forNode(node);
167 abstractValue.set(m_graph, value, m_state.structureClobberState());
168 abstractValue.fixTypeForRepresentation(m_graph, node);
171 void setConstant(Node* node, FrozenValue value)
173 setBuiltInConstant(node, value);
174 m_state.setFoundConstants(true);
177 ALWAYS_INLINE void filterByType(Edge& edge, SpeculatedType type)
179 AbstractValue& value = forNode(edge);
180 if (!value.isType(type))
181 edge.setProofStatus(NeedsCheck);
183 edge.setProofStatus(IsProved);
188 void verifyEdge(Node*, Edge);
189 void verifyEdges(Node*);
191 CodeBlock* m_codeBlock;
193 AbstractStateType& m_state;
194 std::unique_ptr<PhiChildren> m_phiChildren;
197 } } // namespace JSC::DFG
199 #endif // ENABLE(DFG_JIT)
201 #endif // DFGAbstractInterpreter_h