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

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: Win64 fix part II 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 #include "src/compiler/state-values-utils.h"
10
11 namespace v8 {
12 namespace internal {
13 namespace compiler {
14
15
16 LivenessAnalyzer::LivenessAnalyzer(size_t local_count, Zone* zone)
17 : zone_(zone), blocks_(zone), local_count_(local_count), queue_(zone) {}
18
19
20 void LivenessAnalyzer::Print(std::ostream& os) {
21 for (auto block : blocks_) {
22 block->Print(os);
23 os << std::endl;
24 }
25 }
26
27
28 LivenessAnalyzerBlock* LivenessAnalyzer::New() {
29 LivenessAnalyzerBlock* result =
30 new (zone()) LivenessAnalyzerBlock(blocks_.size(), local_count_, zone());
31 blocks_.push_back(result);
32 return result;
33 }
34
35
36 LivenessAnalyzerBlock* LivenessAnalyzer::New(
37 LivenessAnalyzerBlock* predecessor) {
38 LivenessAnalyzerBlock* result = New();
39 result->AddPredecessor(predecessor);
40 return result;
41 }
42
43
44 void LivenessAnalyzer::Queue(LivenessAnalyzerBlock* block) {
45 if (!block->IsQueued()) {
46 block->SetQueued();
47 queue_.push(block);
48 }
49 }
50
51
52 void LivenessAnalyzer::Run(NonLiveFrameStateSlotReplacer* replacer) {
53 // Put all blocks into the queue.
54 DCHECK(queue_.empty());
55 for (auto block : blocks_) {
56 Queue(block);
57 }
58
59 // Compute the fix-point.
60 BitVector working_area(local_count_ == 0 ? 1 : static_cast<int>(local_count_),
Benedikt Meurer 2015/03/17 05:12:03 Is it worth adding a shortcut of the rest for loca
Jarin 2015/03/17 09:22:57 Done.
61 zone_);
62 while (!queue_.empty()) {
63 LivenessAnalyzerBlock* block = queue_.front();
64 queue_.pop();
65 block->Process(&working_area, nullptr);
66
67 for (auto i = block->pred_begin(); i != block->pred_end(); i++) {
68 if ((*i)->UpdateLive(&working_area)) {
69 Queue(*i);
70 }
71 }
72 }
73
74 // Update the frame states according to the liveness.
75 for (auto block : blocks_) {
76 block->Process(&working_area, replacer);
77 }
78 }
79
80
81 void LivenessAnalyzerBlock::Process(BitVector* result,
82 NonLiveFrameStateSlotReplacer* replacer) {
83 queued_ = false;
84
85 // Copy the bitvector to the target bit vector.
86 result->CopyFrom(live_);
87
88 for (auto i = entries_.rbegin(); i != entries_.rend(); i++) {
89 auto entry = *i;
90 switch (entry.kind()) {
91 case Entry::kLookup:
92 result->Add(entry.var());
93 break;
94 case Entry::kBind:
95 result->Remove(entry.var());
96 break;
97 case Entry::kCheckpoint:
98 if (replacer != nullptr) {
99 replacer->ClearNonLiveFrameStateSlots(entry.node(), result);
100 }
101 break;
102 }
103 }
104 }
105
106
107 bool LivenessAnalyzerBlock::UpdateLive(BitVector* working_area) {
108 return live_.UnionIsChanged(*working_area);
109 }
110
111
112 void NonLiveFrameStateSlotReplacer::ClearNonLiveFrameStateSlots(
113 Node* frame_state, BitVector* liveness) {
114 DCHECK_EQ(frame_state->opcode(), IrOpcode::kFrameState);
115 Node* locals_state = frame_state->InputAt(1);
116 DCHECK_EQ(locals_state->opcode(), IrOpcode::kStateValues);
117 int count = static_cast<int>(StateValuesAccess(locals_state).size());
118 DCHECK_EQ(count == 0 ? 1 : count, liveness->length());
119 for (int i = 0; i < count; i++) {
120 bool live = liveness->Contains(i) || permanently_live_.Contains(i);
121 if (!live || locals_state->InputAt(i) != replacement_node_) {
122 Node* new_values = ClearNonLiveStateValues(locals_state, liveness);
123 frame_state->ReplaceInput(1, new_values);
124 break;
125 }
126 }
127 }
128
129
130 Node* NonLiveFrameStateSlotReplacer::ClearNonLiveStateValues(
131 Node* values, BitVector* liveness) {
132 DCHECK(inputs_buffer_.empty());
133 for (Node* node : StateValuesAccess(values)) {
134 // Index of the next variable is its furure index in the inputs buffer,
135 // i.e., the buffer's size.
136 int var = static_cast<int>(inputs_buffer_.size());
137 bool live = liveness->Contains(var) || permanently_live_.Contains(var);
138 inputs_buffer_.push_back(live ? node : replacement_node_);
139 }
140 Node* result = state_values_cache()->GetNodeForValues(
141 inputs_buffer_.empty() ? nullptr : &(inputs_buffer_.front()),
142 inputs_buffer_.size());
143 inputs_buffer_.clear();
144 return result;
145 }
146
147
148 void LivenessAnalyzerBlock::Print(std::ostream& os) {
149 os << "Block " << id();
150 bool first = true;
151 for (LivenessAnalyzerBlock* pred : predecessors_) {
152 if (!first) {
153 os << ", ";
154 } else {
155 os << "; predecessors: ";
156 first = false;
157 }
158 os << pred->id();
159 }
160 os << std::endl;
161
162 for (auto entry : entries_) {
163 os << " ";
164 switch (entry.kind()) {
165 case Entry::kLookup:
166 os << "- Lookup " << entry.var() << std::endl;
167 break;
168 case Entry::kBind:
169 os << "- Bind " << entry.var() << std::endl;
170 break;
171 case Entry::kCheckpoint:
172 os << "- Checkpoint " << entry.node()->id() << std::endl;
173 break;
174 }
175 }
176
177 if (live_.length() > 0) {
178 os << " Live set: ";
179 for (int i = 0; i < live_.length(); i++) {
180 os << (live_.Contains(i) ? "L" : ".");
181 }
182 os << std::endl;
183 }
184 }
185
186 } // namespace compiler
187 } // namespace internal
188 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698