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 "DFGAbstractInterpreterClobberState.h"
31#include "DFGAbstractValue.h"
32#include "DFGBasicBlock.h"
33#include "DFGBlockMap.h"
34#include "DFGGraph.h"
35#include "DFGNodeFlowProjection.h"
36
37namespace JSC { namespace DFG {
38
39class AtTailAbstractState {
40public:
41 AtTailAbstractState(Graph&);
42
43 ~AtTailAbstractState();
44
45 explicit operator bool() const { return true; }
46
47 void initializeTo(BasicBlock* block)
48 {
49 m_block = block;
50 }
51
52 void createValueForNode(NodeFlowProjection);
53
54 AbstractValue& fastForward(AbstractValue& value) { return value; }
55
56 AbstractValue& forNode(NodeFlowProjection);
57 AbstractValue& forNode(Edge edge) { return forNode(edge.node()); }
58
59 ALWAYS_INLINE AbstractValue& forNodeWithoutFastForward(NodeFlowProjection node)
60 {
61 return forNode(node);
62 }
63
64 ALWAYS_INLINE AbstractValue& forNodeWithoutFastForward(Edge edge)
65 {
66 return forNode(edge);
67 }
68
69 ALWAYS_INLINE void fastForwardAndFilterUnproven(AbstractValue& value, SpeculatedType type)
70 {
71 value.filter(type);
72 }
73
74 ALWAYS_INLINE void clearForNode(NodeFlowProjection node)
75 {
76 forNode(node).clear();
77 }
78
79 ALWAYS_INLINE void clearForNode(Edge edge)
80 {
81 clearForNode(edge.node());
82 }
83
84 template<typename... Arguments>
85 ALWAYS_INLINE void setForNode(NodeFlowProjection node, Arguments&&... arguments)
86 {
87 forNode(node).set(m_graph, std::forward<Arguments>(arguments)...);
88 }
89
90 template<typename... Arguments>
91 ALWAYS_INLINE void setForNode(Edge edge, Arguments&&... arguments)
92 {
93 setForNode(edge.node(), std::forward<Arguments>(arguments)...);
94 }
95
96 template<typename... Arguments>
97 ALWAYS_INLINE void setTypeForNode(NodeFlowProjection node, Arguments&&... arguments)
98 {
99 forNode(node).setType(m_graph, std::forward<Arguments>(arguments)...);
100 }
101
102 template<typename... Arguments>
103 ALWAYS_INLINE void setTypeForNode(Edge edge, Arguments&&... arguments)
104 {
105 setTypeForNode(edge.node(), std::forward<Arguments>(arguments)...);
106 }
107
108 template<typename... Arguments>
109 ALWAYS_INLINE void setNonCellTypeForNode(NodeFlowProjection node, Arguments&&... arguments)
110 {
111 forNode(node).setNonCellType(std::forward<Arguments>(arguments)...);
112 }
113
114 template<typename... Arguments>
115 ALWAYS_INLINE void setNonCellTypeForNode(Edge edge, Arguments&&... arguments)
116 {
117 setNonCellTypeForNode(edge.node(), std::forward<Arguments>(arguments)...);
118 }
119
120 ALWAYS_INLINE void makeBytecodeTopForNode(NodeFlowProjection node)
121 {
122 forNode(node).makeBytecodeTop();
123 }
124
125 ALWAYS_INLINE void makeBytecodeTopForNode(Edge edge)
126 {
127 makeBytecodeTopForNode(edge.node());
128 }
129
130 ALWAYS_INLINE void makeHeapTopForNode(NodeFlowProjection node)
131 {
132 forNode(node).makeHeapTop();
133 }
134
135 ALWAYS_INLINE void makeHeapTopForNode(Edge edge)
136 {
137 makeHeapTopForNode(edge.node());
138 }
139
140 unsigned numberOfArguments() const { return m_block->valuesAtTail.numberOfArguments(); }
141 unsigned numberOfLocals() const { return m_block->valuesAtTail.numberOfLocals(); }
142 AbstractValue& operand(int operand) { return m_block->valuesAtTail.operand(operand); }
143 AbstractValue& operand(VirtualRegister operand) { return m_block->valuesAtTail.operand(operand); }
144 AbstractValue& local(size_t index) { return m_block->valuesAtTail.local(index); }
145 AbstractValue& argument(size_t index) { return m_block->valuesAtTail.argument(index); }
146
147 void clobberStructures()
148 {
149 UNREACHABLE_FOR_PLATFORM();
150 }
151
152 void observeInvalidationPoint()
153 {
154 UNREACHABLE_FOR_PLATFORM();
155 }
156
157 BasicBlock* block() const { return m_block; }
158
159 bool isValid() { return m_block->cfaDidFinish; }
160
161 StructureClobberState structureClobberState() const { return m_block->cfaStructureClobberStateAtTail; }
162
163 void setClobberState(AbstractInterpreterClobberState) { }
164 void mergeClobberState(AbstractInterpreterClobberState) { }
165 void setStructureClobberState(StructureClobberState state) { RELEASE_ASSERT(state == m_block->cfaStructureClobberStateAtTail); }
166 void setIsValid(bool isValid) { m_block->cfaDidFinish = isValid; }
167 void setBranchDirection(BranchDirection) { }
168 void setShouldTryConstantFolding(bool) { }
169
170 void trustEdgeProofs() { m_trustEdgeProofs = true; }
171 void dontTrustEdgeProofs() { m_trustEdgeProofs = false; }
172 void setProofStatus(Edge& edge, ProofStatus status)
173 {
174 if (m_trustEdgeProofs)
175 edge.setProofStatus(status);
176 }
177
178private:
179 Graph& m_graph;
180 BlockMap<HashMap<NodeFlowProjection, AbstractValue>> m_valuesAtTailMap;
181 BasicBlock* m_block { nullptr };
182 bool m_trustEdgeProofs { false };
183};
184
185} } // namespace JSC::DFG
186
187#endif // ENABLE(DFG_JIT)
188