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 {
41 WTF_MAKE_FAST_ALLOCATED;
42public:
43 FlowMap(Graph& graph)
44 : m_graph(graph)
45 {
46 resize();
47 }
48
49 // Call this if the number of nodes in the graph has changed. Note that this does not reset any
50 // entries.
51 void resize()
52 {
53 m_map.resize(m_graph.maxNodeCount());
54 if (m_graph.m_form == SSA)
55 m_shadowMap.resize(m_graph.maxNodeCount());
56 }
57
58 Graph& graph() const { return m_graph; }
59
60 ALWAYS_INLINE T& at(unsigned nodeIndex)
61 {
62 return m_map[nodeIndex];
63 }
64
65 ALWAYS_INLINE T& at(Node* node)
66 {
67 return at(node->index());
68 }
69
70 ALWAYS_INLINE T& atShadow(unsigned nodeIndex)
71 {
72 return m_shadowMap[nodeIndex];
73 }
74
75 ALWAYS_INLINE T& atShadow(Node* node)
76 {
77 return atShadow(node->index());
78 }
79
80 ALWAYS_INLINE T& at(unsigned nodeIndex, NodeFlowProjection::Kind kind)
81 {
82 switch (kind) {
83 case NodeFlowProjection::Primary:
84 return at(nodeIndex);
85 case NodeFlowProjection::Shadow:
86 return atShadow(nodeIndex);
87 }
88 RELEASE_ASSERT_NOT_REACHED();
89 return *bitwise_cast<T*>(nullptr);
90 }
91
92 ALWAYS_INLINE T& at(Node* node, NodeFlowProjection::Kind kind)
93 {
94 return at(node->index(), kind);
95 }
96
97 ALWAYS_INLINE T& at(NodeFlowProjection projection)
98 {
99 return at(projection.node(), projection.kind());
100 }
101
102 ALWAYS_INLINE const T& at(unsigned nodeIndex) const { return const_cast<FlowMap*>(this)->at(nodeIndex); }
103 ALWAYS_INLINE const T& at(Node* node) const { return const_cast<FlowMap*>(this)->at(node); }
104 ALWAYS_INLINE const T& atShadow(unsigned nodeIndex) const { return const_cast<FlowMap*>(this)->atShadow(nodeIndex); }
105 ALWAYS_INLINE const T& atShadow(Node* node) const { return const_cast<FlowMap*>(this)->atShadow(node); }
106 ALWAYS_INLINE const T& at(unsigned nodeIndex, NodeFlowProjection::Kind kind) const { return const_cast<FlowMap*>(this)->at(nodeIndex, kind); }
107 ALWAYS_INLINE const T& at(Node* node, NodeFlowProjection::Kind kind) const { return const_cast<FlowMap*>(this)->at(node, kind); }
108 ALWAYS_INLINE const T& at(NodeFlowProjection projection) const { return const_cast<FlowMap*>(this)->at(projection); }
109
110private:
111 Graph& m_graph;
112 Vector<T, 0, UnsafeVectorOverflow> m_map;
113 Vector<T, 0, UnsafeVectorOverflow> m_shadowMap;
114};
115
116} } // namespace JSC::DFG
117
118namespace WTF {
119
120template<typename T>
121void printInternal(PrintStream& out, const JSC::DFG::FlowMap<T>& map)
122{
123 CommaPrinter comma;
124 for (unsigned i = 0; i < map.graph().maxNodeCount(); ++i) {
125 if (JSC::DFG::Node* node = map.graph().nodeAt(i)) {
126 if (const T& value = map.at(node))
127 out.print(comma, node, "=>", value);
128 }
129 }
130 for (unsigned i = 0; i < map.graph().maxNodeCount(); ++i) {
131 if (JSC::DFG::Node* node = map.graph().nodeAt(i)) {
132 if (const T& value = map.atShadow(node))
133 out.print(comma, "shadow(", node, ")=>", value);
134 }
135 }
136}
137
138} // namespace WTF
139
140#endif // ENABLE(DFG_JIT)
141
142