]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGLivenessAnalysisPhase.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGLivenessAnalysisPhase.cpp
1 /*
2 * Copyright (C) 2013 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 #include "config.h"
27 #include "DFGLivenessAnalysisPhase.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGBasicBlockInlines.h"
32 #include "DFGGraph.h"
33 #include "DFGInsertionSet.h"
34 #include "DFGPhase.h"
35 #include "JSCInlines.h"
36
37 namespace JSC { namespace DFG {
38
39 class LivenessAnalysisPhase : public Phase {
40 public:
41 LivenessAnalysisPhase(Graph& graph)
42 : Phase(graph, "liveness analysis")
43 {
44 }
45
46 bool run()
47 {
48 ASSERT(m_graph.m_form == SSA);
49
50 // Liveness is a backwards analysis; the roots are the blocks that
51 // end in a terminal (Return/Throw/ThrowReferenceError). For now, we
52 // use a fixpoint formulation since liveness is a rapid analysis with
53 // convergence guaranteed after O(connectivity).
54
55 // Start by assuming that everything is dead.
56 for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
57 BasicBlock* block = m_graph.block(blockIndex);
58 if (!block)
59 continue;
60 block->ssa->liveAtHead.clear();
61 block->ssa->liveAtTail.clear();
62 }
63
64 do {
65 m_changed = false;
66 for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;)
67 process(blockIndex);
68 } while (m_changed);
69
70 if (!m_graph.block(0)->ssa->liveAtHead.isEmpty()) {
71 DFG_CRASH(
72 m_graph, nullptr,
73 toCString(
74 "Bad liveness analysis result: live at root is not empty: ",
75 nodeListDump(m_graph.block(0)->ssa->liveAtHead)).data());
76 }
77
78 return true;
79 }
80
81 private:
82 void process(BlockIndex blockIndex)
83 {
84 BasicBlock* block = m_graph.block(blockIndex);
85 if (!block)
86 return;
87
88 // FIXME: It's likely that this can be improved, for static analyses that use
89 // HashSets. https://bugs.webkit.org/show_bug.cgi?id=118455
90 m_live = block->ssa->liveAtTail;
91
92 for (unsigned nodeIndex = block->size(); nodeIndex--;) {
93 Node* node = block->at(nodeIndex);
94
95 // Given an Upsilon:
96 //
97 // n: Upsilon(@x, ^p)
98 //
99 // We say that it def's @p and @n and uses @x.
100 //
101 // Given a Phi:
102 //
103 // p: Phi()
104 //
105 // We say nothing. It's neither a use nor a def.
106 //
107 // Given a node:
108 //
109 // n: Thingy(@a, @b, @c)
110 //
111 // We say that it def's @n and uses @a, @b, @c.
112
113 switch (node->op()) {
114 case Upsilon: {
115 Node* phi = node->phi();
116 m_live.remove(phi);
117 m_live.remove(node);
118 m_live.add(node->child1().node());
119 break;
120 }
121
122 case Phi: {
123 break;
124 }
125
126 default:
127 m_live.remove(node);
128 DFG_NODE_DO_TO_CHILDREN(m_graph, node, addChildUse);
129 break;
130 }
131 }
132
133 if (m_live == block->ssa->liveAtHead)
134 return;
135
136 m_changed = true;
137 block->ssa->liveAtHead = m_live;
138 for (unsigned i = block->predecessors.size(); i--;)
139 block->predecessors[i]->ssa->liveAtTail.add(m_live.begin(), m_live.end());
140 }
141
142 void addChildUse(Node*, Edge& edge)
143 {
144 addChildUse(edge);
145 }
146
147 void addChildUse(Edge& edge)
148 {
149 edge.setKillStatus(m_live.add(edge.node()).isNewEntry ? DoesKill : DoesNotKill);
150 }
151
152 bool m_changed;
153 HashSet<Node*> m_live;
154 };
155
156 bool performLivenessAnalysis(Graph& graph)
157 {
158 SamplingRegion samplingRegion("DFG Liveness Analysis Phase");
159 return runPhase<LivenessAnalysisPhase>(graph);
160 }
161
162 } } // namespace JSC::DFG
163
164 #endif // ENABLE(DFG_JIT)
165