1/*
2 * Copyright (C) 2016-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 "DFGFlowIndexing.h"
31#include "DFGGraph.h"
32#include "DFGNode.h"
33
34namespace JSC { namespace DFG {
35
36// This is a mapping from nodes to values that is useful for flow-sensitive analysis. In such an
37// analysis, at every point in the program we need to consider the values of nodes plus the shadow
38// values of Phis. This makes it easy to do both of those things.
39template<typename T>
40class FlowMap {
41public:
42 FlowMap(Graph& graph)
43 : m_graph(graph)
44 {
45 resize();
46 }
47
48 // Call this if the number of nodes in the graph has changed. Note that this does not reset any
49 // entries.
50 void resize()
51 {
52 m_map.resize(m_graph.maxNodeCount());
53 if (m_graph.m_form == SSA)
54 m_shadowMap.resize(m_graph.maxNodeCount());
55 }
56
57 Graph& graph() const { return m_graph; }
58
59 ALWAYS_INLINE T& at(unsigned nodeIndex)
60 {
61 return m_map[nodeIndex];
62 }
63
64 ALWAYS_INLINE T& at(Node* node)
65 {
66 return at(node->index());
67 }
68
69 ALWAYS_INLINE T& atShadow(unsigned nodeIndex)
70 {
71 return m_shadowMap[nodeIndex];
72 }
73
74 ALWAYS_INLINE T& atShadow(Node* node)
75 {
76 return atShadow(node->index());
77 }
78
79 ALWAYS_INLINE T& at(unsigned nodeIndex, NodeFlowProjection::Kind kind)
80 {
81 switch (kind) {
82 case NodeFlowProjection::Primary:
83 return at(nodeIndex);
84 case NodeFlowProjection::Shadow:
85 return atShadow(nodeIndex);
86 }
87 RELEASE_ASSERT_NOT_REACHED();
88 return *bitwise_cast<T*>(nullptr);
89 }
90
91 ALWAYS_INLINE T& at(Node* node, NodeFlowProjection::Kind kind)
92 {
93 return at(node->index(), kind);
94 }
95
96 ALWAYS_INLINE T& at(NodeFlowProjection projection)
97 {
98 return at(projection.node(), projection.kind());
99 }
100
101 ALWAYS_INLINE const T& at(unsigned nodeIndex) const { return const_cast<FlowMap*>(this)->at(nodeIndex); }
102 ALWAYS_INLINE const T& at(Node* node) const { return const_cast<FlowMap*>(this)->at(node); }
103 ALWAYS_INLINE const T& atShadow(unsigned nodeIndex) const { return const_cast<FlowMap*>(this)->atShadow(nodeIndex); }
104 ALWAYS_INLINE const T& atShadow(Node* node) const { return const_cast<FlowMap*>(this)->atShadow(node); }
105 ALWAYS_INLINE const T& at(unsigned nodeIndex, NodeFlowProjection::Kind kind) const { return const_cast<FlowMap*>(this)->at(nodeIndex, kind); }
106 ALWAYS_INLINE const T& at(Node* node, NodeFlowProjection::Kind kind) const { return const_cast<FlowMap*>(this)->at(node, kind); }
107 ALWAYS_INLINE const T& at(NodeFlowProjection projection) const { return const_cast<FlowMap*>(this)->at(projection); }
108
109private:
110 Graph& m_graph;
111 Vector<T, 0, UnsafeVectorOverflow> m_map;
112 Vector<T, 0, UnsafeVectorOverflow> m_shadowMap;
113};
114
115} } // namespace JSC::DFG
116
117namespace WTF {
118
119template<typename T>
120void printInternal(PrintStream& out, const JSC::DFG::FlowMap<T>& map)
121{
122 CommaPrinter comma;
123 for (unsigned i = 0; i < map.graph().maxNodeCount(); ++i) {
124 if (JSC::DFG::Node* node = map.graph().nodeAt(i)) {
125 if (const T& value = map.at(node))
126 out.print(comma, node, "=>", value);
127 }
128 }
129 for (unsigned i = 0; i < map.graph().maxNodeCount(); ++i) {
130 if (JSC::DFG::Node* node = map.graph().nodeAt(i)) {
131 if (const T& value = map.atShadow(node))
132 out.print(comma, "shadow(", node, ")=>", value);
133 }
134 }
135}
136
137} // namespace WTF
138
139#endif // ENABLE(DFG_JIT)
140
141