blob: ee862c0194efae0e09ff4e1fe178f96ab6e6252b [file] [log] [blame]
oliver@apple.com827d2cf2013-07-25 04:04:45 +00001/*
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"
ossy@webkit.orgbeb0de42014-02-17 19:00:03 +000027#include "DFGFlushLivenessAnalysisPhase.h"
oliver@apple.com827d2cf2013-07-25 04:04:45 +000028
29#if ENABLE(DFG_JIT)
30
31#include "DFGBasicBlockInlines.h"
fpizlo@apple.com0bef2a12014-02-10 19:26:29 +000032#include "DFGGraph.h"
oliver@apple.com827d2cf2013-07-25 04:04:45 +000033#include "DFGInsertionSet.h"
34#include "DFGPhase.h"
oliver@apple.com237b1462013-07-25 04:05:36 +000035#include "OperandsInlines.h"
fpizlo@apple.comfb7eff22014-02-11 01:45:50 +000036#include "JSCInlines.h"
oliver@apple.com827d2cf2013-07-25 04:04:45 +000037
38namespace JSC { namespace DFG {
39
40class FlushLivenessAnalysisPhase : public Phase {
41public:
42 FlushLivenessAnalysisPhase(Graph& graph)
43 : Phase(graph, "flush-liveness analysis")
44 {
45 }
46
47 bool run()
48 {
49 ASSERT(m_graph.m_form == SSA);
50
51 // Liveness is a backwards analysis; the roots are the blocks that
oliver@apple.com1fc04182013-08-19 19:40:13 +000052 // end in a terminal (Return/Unreachable). For now, we
oliver@apple.com827d2cf2013-07-25 04:04:45 +000053 // use a fixpoint formulation since liveness is a rapid analysis with
54 // convergence guaranteed after O(connectivity).
55
56 // Start by assuming that everything is dead.
57 for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
58 BasicBlock* block = m_graph.block(blockIndex);
59 if (!block)
60 continue;
fpizlo@apple.coma62d4822013-10-06 04:22:43 +000061 block->ssa->flushAtHead.fill(FlushedAt());
62 block->ssa->flushAtTail.fill(FlushedAt());
oliver@apple.com827d2cf2013-07-25 04:04:45 +000063 }
64
65 do {
66 m_changed = false;
67 for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;)
68 process(blockIndex);
69 } while (m_changed);
70
fpizlo@apple.coma62d4822013-10-06 04:22:43 +000071 Operands<FlushedAt>& root = m_graph.block(0)->ssa->flushAtHead;
oliver@apple.com827d2cf2013-07-25 04:04:45 +000072 for (unsigned i = root.size(); i--;) {
73 if (root.isArgument(i)) {
fpizlo@apple.coma62d4822013-10-06 04:22:43 +000074 if (!root[i]
75 || root[i] == FlushedAt(FlushedJSValue, VirtualRegister(root.operandForIndex(i))))
oliver@apple.com827d2cf2013-07-25 04:04:45 +000076 continue;
77 } else {
fpizlo@apple.coma62d4822013-10-06 04:22:43 +000078 if (!root[i])
oliver@apple.com827d2cf2013-07-25 04:04:45 +000079 continue;
80 }
81 dataLog(
82 "Bad flush liveness analysis result: bad flush liveness at root: ",
83 root, "\n");
84 dataLog("IR at time of error:\n");
85 m_graph.dump();
86 CRASH();
87 }
88
89 return true;
90 }
91
92private:
93 void process(BlockIndex blockIndex)
94 {
95 BasicBlock* block = m_graph.block(blockIndex);
96 if (!block)
97 return;
98
fpizlo@apple.coma62d4822013-10-06 04:22:43 +000099 m_live = block->ssa->flushAtTail;
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000100
101 for (unsigned nodeIndex = block->size(); nodeIndex--;) {
102 Node* node = block->at(nodeIndex);
103
104 switch (node->op()) {
105 case SetLocal: {
106 VariableAccessData* variable = node->variableAccessData();
fpizlo@apple.coma62d4822013-10-06 04:22:43 +0000107 FlushedAt& current = m_live.operand(variable->local());
108 if (!!current && current != variable->flushedAt())
109 reportError(node);
110 current = FlushedAt();
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000111 break;
112 }
113
114 case GetArgument: {
115 VariableAccessData* variable = node->variableAccessData();
fpizlo@apple.coma62d4822013-10-06 04:22:43 +0000116 ASSERT(variable->local() == variable->machineLocal());
117 ASSERT(variable->local().isArgument());
118 FlushedAt& current = m_live.operand(variable->local());
119 if (!!current && current != variable->flushedAt())
120 reportError(node);
121 current = FlushedAt(FlushedJSValue, node->local());
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000122 break;
123 }
124
125 case Flush:
126 case GetLocal: {
127 VariableAccessData* variable = node->variableAccessData();
fpizlo@apple.coma62d4822013-10-06 04:22:43 +0000128 FlushedAt& current = m_live.operand(variable->local());
129 if (!!current && current != variable->flushedAt())
130 reportError(node);
131 current = variable->flushedAt();
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000132 break;
133 }
134
135 default:
136 break;
137 }
138 }
139
fpizlo@apple.coma62d4822013-10-06 04:22:43 +0000140 if (m_live == block->ssa->flushAtHead)
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000141 return;
142
143 m_changed = true;
fpizlo@apple.coma62d4822013-10-06 04:22:43 +0000144 block->ssa->flushAtHead = m_live;
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000145 for (unsigned i = block->predecessors.size(); i--;) {
146 BasicBlock* predecessor = block->predecessors[i];
147 for (unsigned j = m_live.size(); j--;) {
fpizlo@apple.coma62d4822013-10-06 04:22:43 +0000148 FlushedAt& predecessorFlush = predecessor->ssa->flushAtTail[j];
149 FlushedAt myFlush = m_live[j];
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000150
151 // Three possibilities:
152 // 1) Predecessor format is Dead, in which case it acquires our format.
commit-queue@webkit.org0bc8b5d42013-10-18 16:55:42 +0000153 // 2) Predecessor format is not Dead but our format is dead, in which
154 // case we acquire the predecessor format.
155 // 3) Predecessor format is identical to our format, in which case we
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000156 // do nothing.
commit-queue@webkit.org0bc8b5d42013-10-18 16:55:42 +0000157 // 4) Predecessor format is different from our format and it's not Dead,
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000158 // in which case we have an erroneous set of Flushes and SetLocals.
commit-queue@webkit.org0bc8b5d42013-10-18 16:55:42 +0000159
fpizlo@apple.coma62d4822013-10-06 04:22:43 +0000160 if (!predecessorFlush) {
161 predecessorFlush = myFlush;
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000162 continue;
163 }
commit-queue@webkit.org0bc8b5d42013-10-18 16:55:42 +0000164
165 if (!myFlush) {
166 m_live[j] = predecessorFlush;
167 continue;
168 }
169
fpizlo@apple.coma62d4822013-10-06 04:22:43 +0000170 if (predecessorFlush == myFlush)
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000171 continue;
172
173 dataLog(
174 "Bad Flush merge at edge ", *predecessor, " -> ", *block,
175 ", local variable r", m_live.operandForIndex(j), ": ", *predecessor,
fpizlo@apple.coma62d4822013-10-06 04:22:43 +0000176 " has ", predecessorFlush, " and ", *block, " has ", myFlush, ".\n");
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000177 dataLog("IR at time of error:\n");
178 m_graph.dump();
179 CRASH();
180 }
181 }
182 }
183
fpizlo@apple.coma62d4822013-10-06 04:22:43 +0000184 NO_RETURN_DUE_TO_CRASH void reportError(Node* node)
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000185 {
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000186 dataLog(
fpizlo@apple.coma62d4822013-10-06 04:22:43 +0000187 "Bad flush merge at node ", node, ", r", node->local(), ": node claims ",
188 node->variableAccessData()->flushedAt(), " but backwards flow claims ",
189 m_live.operand(node->local()), ".\n");
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000190 dataLog("IR at time of error:\n");
191 m_graph.dump();
192 CRASH();
193 }
194
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000195 bool m_changed;
fpizlo@apple.coma62d4822013-10-06 04:22:43 +0000196 Operands<FlushedAt> m_live;
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000197};
198
199bool performFlushLivenessAnalysis(Graph& graph)
200{
201 SamplingRegion samplingRegion("DFG Flush-Liveness Analysis Phase");
202 return runPhase<FlushLivenessAnalysisPhase>(graph);
203}
204
205} } // namespace JSC::DFG
206
207#endif // ENABLE(DFG_JIT)
208