2 * Copyright (C) 2013, 2014 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"
36 namespace JSC
{ namespace DFG
{
38 template<typename AbstractStateType
>
39 class AbstractInterpreter
{
41 AbstractInterpreter(Graph
&, AbstractStateType
&);
42 ~AbstractInterpreter();
44 AbstractValue
& forNode(Node
* node
)
46 return m_state
.forNode(node
);
49 AbstractValue
& forNode(Edge edge
)
51 return forNode(edge
.node());
54 Operands
<AbstractValue
>& variables()
56 return m_state
.variables();
59 bool needsTypeCheck(Node
* node
, SpeculatedType typesPassedThrough
)
61 return !forNode(node
).isType(typesPassedThrough
);
64 bool needsTypeCheck(Edge edge
, SpeculatedType typesPassedThrough
)
66 return needsTypeCheck(edge
.node(), typesPassedThrough
);
69 bool needsTypeCheck(Edge edge
)
71 return needsTypeCheck(edge
, typeFilterFor(edge
.useKind()));
74 // Abstractly executes the given node. The new abstract state is stored into an
75 // abstract stack stored in *this. Loads of local variables (that span
76 // basic blocks) interrogate the basic block's notion of the state at the head.
77 // Stores to local variables are handled in endBasicBlock(). This returns true
78 // if execution should continue past this node. Notably, it will return true
79 // for block terminals, so long as those terminals are not Return or Unreachable.
81 // This is guaranteed to be equivalent to doing:
83 // if (state.startExecuting(index)) {
84 // state.executeEdges(index);
85 // result = state.executeEffects(index);
88 bool execute(unsigned indexInBlock
);
91 // Indicate the start of execution of the node. It resets any state in the node,
92 // that is progressively built up by executeEdges() and executeEffects(). In
93 // particular, this resets canExit(), so if you want to "know" between calls of
94 // startExecuting() and executeEdges()/Effects() whether the last run of the
95 // analysis concluded that the node can exit, you should probably set that
96 // information aside prior to calling startExecuting().
97 bool startExecuting(Node
*);
98 bool startExecuting(unsigned indexInBlock
);
100 // Abstractly execute the edges of the given node. This runs filterEdgeByUse()
101 // on all edges of the node. You can skip this step, if you have already used
102 // filterEdgeByUse() (or some equivalent) on each edge.
103 void executeEdges(Node
*);
104 void executeEdges(unsigned indexInBlock
);
106 ALWAYS_INLINE
void filterEdgeByUse(Node
* node
, Edge
& edge
)
108 ASSERT(mayHaveTypeCheck(edge
.useKind()) || !needsTypeCheck(edge
));
109 filterByType(node
, edge
, typeFilterFor(edge
.useKind()));
112 // Abstractly execute the effects of the given node. This changes the abstract
113 // state assuming that edges have already been filtered.
114 bool executeEffects(unsigned indexInBlock
);
115 bool executeEffects(unsigned clobberLimit
, Node
*);
117 void dump(PrintStream
& out
);
120 FiltrationResult
filter(T node
, const StructureSet
& set
)
122 return filter(forNode(node
), set
);
126 FiltrationResult
filterArrayModes(T node
, ArrayModes arrayModes
)
128 return filterArrayModes(forNode(node
), arrayModes
);
132 FiltrationResult
filter(T node
, SpeculatedType type
)
134 return filter(forNode(node
), type
);
138 FiltrationResult
filterByValue(T node
, JSValue value
)
140 return filterByValue(forNode(node
), value
);
143 FiltrationResult
filter(AbstractValue
&, const StructureSet
&);
144 FiltrationResult
filterArrayModes(AbstractValue
&, ArrayModes
);
145 FiltrationResult
filter(AbstractValue
&, SpeculatedType
);
146 FiltrationResult
filterByValue(AbstractValue
&, JSValue
);
149 void clobberWorld(const CodeOrigin
&, unsigned indexInBlock
);
150 void clobberCapturedVars(const CodeOrigin
&);
151 void clobberStructures(unsigned indexInBlock
);
154 UnknownBooleanResult
,
158 BooleanResult
booleanResult(Node
*, AbstractValue
&);
160 void setBuiltInConstant(Node
* node
, JSValue value
)
162 AbstractValue
& abstractValue
= forNode(node
);
163 abstractValue
.set(m_graph
, value
);
164 abstractValue
.fixTypeForRepresentation(node
);
167 void setConstant(Node
* node
, JSValue value
)
169 setBuiltInConstant(node
, value
);
170 m_state
.setFoundConstants(true);
173 ALWAYS_INLINE
void filterByType(Node
* node
, Edge
& edge
, SpeculatedType type
)
175 AbstractValue
& value
= forNode(edge
);
176 if (!value
.isType(type
)) {
177 node
->setCanExit(true);
178 edge
.setProofStatus(NeedsCheck
);
180 edge
.setProofStatus(IsProved
);
185 void verifyEdge(Node
*, Edge
);
186 void verifyEdges(Node
*);
188 CodeBlock
* m_codeBlock
;
190 AbstractStateType
& m_state
;
193 } } // namespace JSC::DFG
195 #endif // ENABLE(DFG_JIT)
197 #endif // DFGAbstractInterpreter_h