Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(625)

Side by Side Diff: src/compiler/liveness-analyzer.cc

Issue 949743002: [turbofan] Variable liveness analysis for deopt (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Test tweaks Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/compiler/liveness-analyzer.h"
6 #include "src/compiler/js-graph.h"
7 #include "src/compiler/node.h"
8 #include "src/compiler/node-matchers.h"
9
10 namespace v8 {
11 namespace internal {
12 namespace compiler {
13
14
15 LivenessAnalyzer::LivenessAnalyzer(size_t local_count, Zone* zone)
16 : zone_(zone), blocks_(zone), local_count_(local_count), queue_(zone) {}
17
18
19 void LivenessAnalyzer::Print(std::ostream& os) {
20 for (auto block : blocks_) {
21 block->Print(os);
22 os << std::endl;
23 }
24 }
25
26
27 LivenessAnalyzerBlock* LivenessAnalyzer::New() {
28 LivenessAnalyzerBlock* result =
29 new (zone()) LivenessAnalyzerBlock(blocks_.size(), local_count_, zone());
30 blocks_.push_back(result);
31 return result;
32 }
33
34
35 LivenessAnalyzerBlock* LivenessAnalyzer::New(
36 LivenessAnalyzerBlock* predecessor) {
37 LivenessAnalyzerBlock* result = New();
38 result->AddPredecessor(predecessor);
39 return result;
40 }
41
42
43 void LivenessAnalyzer::Queue(LivenessAnalyzerBlock* block) {
44 if (!block->IsQueued()) {
45 block->SetQueued();
46 queue_.push(block);
47 }
48 }
49
50
51 void LivenessAnalyzer::Run(FrameStateRelaxer* relaxer) {
52 // Put all blocks into the queue.
53 DCHECK(queue_.empty());
54 for (auto block : blocks_) {
55 Queue(block);
56 }
57
58 // Compute the fix-point.
59 ZoneVector<bool> working_area(local_count_, false, zone_);
60 while (!queue_.empty()) {
61 LivenessAnalyzerBlock* block = queue_.front();
62 queue_.pop();
63 block->Process(&working_area, nullptr);
64
65 for (auto i = block->pred_begin(); i != block->pred_end(); i++) {
66 if ((*i)->UpdateLive(&working_area)) {
67 Queue(*i);
68 }
69 }
70 }
71
72 // Update the frame states according to the liveness.
73 for (auto block : blocks_) {
74 block->Process(&working_area, relaxer);
75 }
76 }
77
78
79 void LivenessAnalyzerBlock::Process(ZoneVector<bool>* result,
80 FrameStateRelaxer* relaxer) {
81 queued_ = false;
82
83 // Copy the bitvector to the target bit vector.
84 *result = live_;
85
86 for (auto i = entries_.rbegin(); i != entries_.rend(); i++) {
87 auto entry = *i;
88 switch (entry.kind()) {
89 case Entry::kLookup:
90 (*result)[entry.var()] = true;
91 break;
92 case Entry::kBind:
93 (*result)[entry.var()] = false;
94 break;
95 case Entry::kCheckpoint:
96 if (relaxer != nullptr) {
97 relaxer->RelaxFrameState(entry.node(), result);
98 }
99 break;
100 }
101 }
102 }
103
104
105 bool LivenessAnalyzerBlock::UpdateLive(ZoneVector<bool>* working_area) {
106 bool changed = false;
107 for (size_t i = 0; i < working_area->size(); i++) {
108 if ((*working_area)[i] && !live_[i]) {
109 // We can only make variables live during propagation.
110 live_[i] = true;
111 changed = true;
112 }
113 }
114 return changed;
115 }
116
117
118 void FrameStateRelaxer::RelaxFrameState(Node* frame_state,
119 ZoneVector<bool>* liveness) {
120 DCHECK_EQ(frame_state->opcode(), IrOpcode::kFrameState);
121 Node* locals_state = frame_state->InputAt(1);
122 DCHECK_EQ(locals_state->opcode(), IrOpcode::kStateValues);
123 int count = locals_state->InputCount();
124 DCHECK_EQ(count, static_cast<int>(liveness->size()));
125 for (int i = 0; i < count; i++) {
126 bool live = (*liveness)[i] || blacklist_[i];
127 if (!live || locals_state->InputAt(i) != replacement_node_) {
128 Node* new_values = RelaxStateValues(locals_state, liveness);
129 frame_state->ReplaceInput(1, new_values);
130 break;
131 }
132 }
133 }
134
135
136 Node* FrameStateRelaxer::RelaxStateValues(Node* values,
137 ZoneVector<bool>* liveness) {
138 int count = values->InputCount();
139 ZoneVector<Node*> inputs(count, nullptr, local_zone());
140 for (int i = 0; i < count; i++) {
141 bool live = (*liveness)[i] || blacklist_[i];
142 inputs[i] = live ? values->InputAt(i) : replacement_node_;
143 }
144 const Operator* op = js_graph()->common()->StateValues(count);
145 return js_graph()->graph()->NewNode(op, count,
146 count == 0 ? nullptr : &(inputs.front()));
147 }
148
149
150 void LivenessAnalyzerBlock::Print(std::ostream& os) {
151 os << "Block " << id();
152 bool first = true;
153 for (LivenessAnalyzerBlock* pred : predecessors_) {
154 if (!first) {
155 os << ", ";
156 } else {
157 os << "; predecessors: ";
158 first = false;
159 }
160 os << pred->id();
161 }
162 os << std::endl;
163
164 for (auto entry : entries_) {
165 os << " ";
166 switch (entry.kind()) {
167 case Entry::kLookup:
168 os << "- Lookup " << entry.var() << std::endl;
169 break;
170 case Entry::kBind:
171 os << "- Bind " << entry.var() << std::endl;
172 break;
173 case Entry::kCheckpoint:
174 os << "- Checkpoint " << entry.node()->id() << std::endl;
175 break;
176 }
177 }
178
179 if (live_.size() > 0) {
180 os << " Live set: ";
181 for (bool live : live_) {
182 os << (live ? "L" : ".");
183 }
184 os << std::endl;
185 }
186 }
187
188 } // namespace compiler
189 } // namespace internal
190 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698