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

Side by Side Diff: src/compiler/bytecode-analysis.cc

Issue 2552723004: [ignition/turbofan] Wrap bytecode liveness bitvectors (Closed)
Patch Set: Created 4 years 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
« no previous file with comments | « src/compiler/bytecode-analysis.h ('k') | src/compiler/bytecode-graph-builder.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/bytecode-analysis.h" 5 #include "src/compiler/bytecode-analysis.h"
6 6
7 #include "src/interpreter/bytecode-array-iterator.h" 7 #include "src/interpreter/bytecode-array-iterator.h"
8 #include "src/interpreter/bytecode-array-random-iterator.h" 8 #include "src/interpreter/bytecode-array-random-iterator.h"
9 #include "src/objects-inl.h" 9 #include "src/objects-inl.h"
10 10
11 namespace v8 { 11 namespace v8 {
12 namespace internal { 12 namespace internal {
13 namespace compiler { 13 namespace compiler {
14 14
15 using namespace interpreter; 15 using namespace interpreter;
16 16
17 BytecodeAnalysis::BytecodeAnalysis(Handle<BytecodeArray> bytecode_array, 17 BytecodeAnalysis::BytecodeAnalysis(Handle<BytecodeArray> bytecode_array,
18 Zone* zone, bool do_liveness_analysis) 18 Zone* zone, bool do_liveness_analysis)
19 : bytecode_array_(bytecode_array), 19 : bytecode_array_(bytecode_array),
20 do_liveness_analysis_(do_liveness_analysis), 20 do_liveness_analysis_(do_liveness_analysis),
21 zone_(zone), 21 zone_(zone),
22 loop_stack_(zone), 22 loop_stack_(zone),
23 loop_end_index_queue_(zone), 23 loop_end_index_queue_(zone),
24 end_to_header_(zone), 24 end_to_header_(zone),
25 header_to_parent_(zone), 25 header_to_parent_(zone),
26 liveness_map_(bytecode_array->length(), zone) {} 26 liveness_map_(bytecode_array->length(), zone) {}
27 27
28 namespace { 28 namespace {
29 29
30 void UpdateInLiveness(Bytecode bytecode, BitVector& in_liveness, 30 void UpdateInLiveness(Bytecode bytecode, BytecodeLivenessState& in_liveness,
31 const BytecodeArrayAccessor& accessor) { 31 const BytecodeArrayAccessor& accessor) {
32 int num_operands = Bytecodes::NumberOfOperands(bytecode); 32 int num_operands = Bytecodes::NumberOfOperands(bytecode);
33 const OperandType* operand_types = Bytecodes::GetOperandTypes(bytecode); 33 const OperandType* operand_types = Bytecodes::GetOperandTypes(bytecode);
34 AccumulatorUse accumulator_use = Bytecodes::GetAccumulatorUse(bytecode); 34 AccumulatorUse accumulator_use = Bytecodes::GetAccumulatorUse(bytecode);
35 35
36 if (accumulator_use == AccumulatorUse::kWrite) { 36 if (accumulator_use == AccumulatorUse::kWrite) {
37 in_liveness.Remove(in_liveness.length() - 1); 37 in_liveness.MarkAccumulatorDead();
38 } 38 }
39 for (int i = 0; i < num_operands; ++i) { 39 for (int i = 0; i < num_operands; ++i) {
40 switch (operand_types[i]) { 40 switch (operand_types[i]) {
41 case OperandType::kRegOut: { 41 case OperandType::kRegOut: {
42 interpreter::Register r = accessor.GetRegisterOperand(i); 42 interpreter::Register r = accessor.GetRegisterOperand(i);
43 if (!r.is_parameter()) { 43 if (!r.is_parameter()) {
44 in_liveness.Remove(r.index()); 44 in_liveness.MarkRegisterDead(r.index());
45 } 45 }
46 break; 46 break;
47 } 47 }
48 case OperandType::kRegOutPair: { 48 case OperandType::kRegOutPair: {
49 interpreter::Register r = accessor.GetRegisterOperand(i); 49 interpreter::Register r = accessor.GetRegisterOperand(i);
50 if (!r.is_parameter()) { 50 if (!r.is_parameter()) {
51 DCHECK(!interpreter::Register(r.index() + 1).is_parameter()); 51 DCHECK(!interpreter::Register(r.index() + 1).is_parameter());
52 in_liveness.Remove(r.index()); 52 in_liveness.MarkRegisterDead(r.index());
53 in_liveness.Remove(r.index() + 1); 53 in_liveness.MarkRegisterDead(r.index() + 1);
54 } 54 }
55 break; 55 break;
56 } 56 }
57 case OperandType::kRegOutTriple: { 57 case OperandType::kRegOutTriple: {
58 interpreter::Register r = accessor.GetRegisterOperand(i); 58 interpreter::Register r = accessor.GetRegisterOperand(i);
59 if (!r.is_parameter()) { 59 if (!r.is_parameter()) {
60 DCHECK(!interpreter::Register(r.index() + 1).is_parameter()); 60 DCHECK(!interpreter::Register(r.index() + 1).is_parameter());
61 DCHECK(!interpreter::Register(r.index() + 2).is_parameter()); 61 DCHECK(!interpreter::Register(r.index() + 2).is_parameter());
62 in_liveness.Remove(r.index()); 62 in_liveness.MarkRegisterDead(r.index());
63 in_liveness.Remove(r.index() + 1); 63 in_liveness.MarkRegisterDead(r.index() + 1);
64 in_liveness.Remove(r.index() + 2); 64 in_liveness.MarkRegisterDead(r.index() + 2);
65 } 65 }
66 break; 66 break;
67 } 67 }
68 default: 68 default:
69 DCHECK(!Bytecodes::IsRegisterOutputOperandType(operand_types[i])); 69 DCHECK(!Bytecodes::IsRegisterOutputOperandType(operand_types[i]));
70 break; 70 break;
71 } 71 }
72 } 72 }
73 73
74 if (accumulator_use == AccumulatorUse::kRead) { 74 if (accumulator_use == AccumulatorUse::kRead) {
75 in_liveness.Add(in_liveness.length() - 1); 75 in_liveness.MarkAccumulatorLive();
76 } 76 }
77 for (int i = 0; i < num_operands; ++i) { 77 for (int i = 0; i < num_operands; ++i) {
78 switch (operand_types[i]) { 78 switch (operand_types[i]) {
79 case OperandType::kReg: { 79 case OperandType::kReg: {
80 interpreter::Register r = accessor.GetRegisterOperand(i); 80 interpreter::Register r = accessor.GetRegisterOperand(i);
81 if (!r.is_parameter()) { 81 if (!r.is_parameter()) {
82 in_liveness.Add(r.index()); 82 in_liveness.MarkRegisterLive(r.index());
83 } 83 }
84 break; 84 break;
85 } 85 }
86 case OperandType::kRegPair: { 86 case OperandType::kRegPair: {
87 interpreter::Register r = accessor.GetRegisterOperand(i); 87 interpreter::Register r = accessor.GetRegisterOperand(i);
88 if (!r.is_parameter()) { 88 if (!r.is_parameter()) {
89 DCHECK(!interpreter::Register(r.index() + 1).is_parameter()); 89 DCHECK(!interpreter::Register(r.index() + 1).is_parameter());
90 in_liveness.Add(r.index()); 90 in_liveness.MarkRegisterLive(r.index());
91 in_liveness.Add(r.index() + 1); 91 in_liveness.MarkRegisterLive(r.index() + 1);
92 } 92 }
93 break; 93 break;
94 } 94 }
95 case OperandType::kRegList: { 95 case OperandType::kRegList: {
96 interpreter::Register r = accessor.GetRegisterOperand(i++); 96 interpreter::Register r = accessor.GetRegisterOperand(i++);
97 uint32_t reg_count = accessor.GetRegisterCountOperand(i); 97 uint32_t reg_count = accessor.GetRegisterCountOperand(i);
98 if (!r.is_parameter()) { 98 if (!r.is_parameter()) {
99 for (uint32_t j = 0; j < reg_count; ++j) { 99 for (uint32_t j = 0; j < reg_count; ++j) {
100 DCHECK(!interpreter::Register(r.index() + j).is_parameter()); 100 DCHECK(!interpreter::Register(r.index() + j).is_parameter());
101 in_liveness.Add(r.index() + j); 101 in_liveness.MarkRegisterLive(r.index() + j);
102 } 102 }
103 } 103 }
104 } 104 }
105 default: 105 default:
106 DCHECK(!Bytecodes::IsRegisterInputOperandType(operand_types[i])); 106 DCHECK(!Bytecodes::IsRegisterInputOperandType(operand_types[i]));
107 break; 107 break;
108 } 108 }
109 } 109 }
110 } 110 }
111 111
112 void UpdateOutLiveness(Bytecode bytecode, BitVector& out_liveness, 112 void UpdateOutLiveness(Bytecode bytecode, BytecodeLivenessState& out_liveness,
113 BitVector* next_bytecode_in_liveness, 113 BytecodeLivenessState* next_bytecode_in_liveness,
114 const BytecodeArrayAccessor& accessor, 114 const BytecodeArrayAccessor& accessor,
115 const BytecodeLivenessMap& liveness_map) { 115 const BytecodeLivenessMap& liveness_map) {
116 int current_offset = accessor.current_offset(); 116 int current_offset = accessor.current_offset();
117 const Handle<BytecodeArray>& bytecode_array = accessor.bytecode_array(); 117 const Handle<BytecodeArray>& bytecode_array = accessor.bytecode_array();
118 118
119 // Update from jump target (if any). Skip loops, we update these manually in 119 // Update from jump target (if any). Skip loops, we update these manually in
120 // the liveness iterations. 120 // the liveness iterations.
121 if (Bytecodes::IsForwardJump(bytecode)) { 121 if (Bytecodes::IsForwardJump(bytecode)) {
122 int target_offset = accessor.GetJumpTargetOffset(); 122 int target_offset = accessor.GetJumpTargetOffset();
123 out_liveness.Union(*liveness_map.GetInLiveness(target_offset)); 123 out_liveness.Union(*liveness_map.GetInLiveness(target_offset));
124 } 124 }
125 125
126 // Update from next bytecode (unless there isn't one or this is an 126 // Update from next bytecode (unless there isn't one or this is an
127 // unconditional jump). 127 // unconditional jump).
128 if (next_bytecode_in_liveness != nullptr && 128 if (next_bytecode_in_liveness != nullptr &&
129 !Bytecodes::IsUnconditionalJump(bytecode)) { 129 !Bytecodes::IsUnconditionalJump(bytecode)) {
130 out_liveness.Union(*next_bytecode_in_liveness); 130 out_liveness.Union(*next_bytecode_in_liveness);
131 } 131 }
132 132
133 // Update from exception handler (if any). 133 // Update from exception handler (if any).
134 if (!interpreter::Bytecodes::IsWithoutExternalSideEffects(bytecode)) { 134 if (!interpreter::Bytecodes::IsWithoutExternalSideEffects(bytecode)) {
135 int handler_context; 135 int handler_context;
136 // TODO(leszeks): We should look up this range only once per entry. 136 // TODO(leszeks): We should look up this range only once per entry.
137 HandlerTable* table = HandlerTable::cast(bytecode_array->handler_table()); 137 HandlerTable* table = HandlerTable::cast(bytecode_array->handler_table());
138 int handler_offset = 138 int handler_offset =
139 table->LookupRange(current_offset, &handler_context, nullptr); 139 table->LookupRange(current_offset, &handler_context, nullptr);
140 140
141 if (handler_offset != -1) { 141 if (handler_offset != -1) {
142 out_liveness.Union(*liveness_map.GetInLiveness(handler_offset)); 142 out_liveness.Union(*liveness_map.GetInLiveness(handler_offset));
143 out_liveness.Add(handler_context); 143 out_liveness.MarkRegisterLive(handler_context);
144 } 144 }
145 } 145 }
146 } 146 }
147 147
148 } // namespace 148 } // namespace
149 149
150 void BytecodeAnalysis::Analyze() { 150 void BytecodeAnalysis::Analyze() {
151 loop_stack_.push(-1); 151 loop_stack_.push(-1);
152 152
153 BitVector* next_bytecode_in_liveness = nullptr; 153 BytecodeLivenessState* next_bytecode_in_liveness = nullptr;
154 154
155 BytecodeArrayRandomIterator iterator(bytecode_array(), zone()); 155 BytecodeArrayRandomIterator iterator(bytecode_array(), zone());
156 for (iterator.GoToEnd(); iterator.IsValid(); --iterator) { 156 for (iterator.GoToEnd(); iterator.IsValid(); --iterator) {
157 Bytecode bytecode = iterator.current_bytecode(); 157 Bytecode bytecode = iterator.current_bytecode();
158 int current_offset = iterator.current_offset(); 158 int current_offset = iterator.current_offset();
159 159
160 if (bytecode == Bytecode::kJumpLoop) { 160 if (bytecode == Bytecode::kJumpLoop) {
161 // Every byte up to and including the last byte within the backwards jump 161 // Every byte up to and including the last byte within the backwards jump
162 // instruction is considered part of the loop, set loop end accordingly. 162 // instruction is considered part of the loop, set loop end accordingly.
163 int loop_end = current_offset + iterator.current_bytecode_size(); 163 int loop_end = current_offset + iterator.current_bytecode_size();
164 PushLoop(iterator.GetJumpTargetOffset(), loop_end); 164 PushLoop(iterator.GetJumpTargetOffset(), loop_end);
165 165
166 // Save the index so that we can do another pass later. 166 // Save the index so that we can do another pass later.
167 if (do_liveness_analysis_) { 167 if (do_liveness_analysis_) {
168 loop_end_index_queue_.push_back(iterator.current_index()); 168 loop_end_index_queue_.push_back(iterator.current_index());
169 } 169 }
170 } else if (current_offset == loop_stack_.top()) { 170 } else if (current_offset == loop_stack_.top()) {
171 loop_stack_.pop(); 171 loop_stack_.pop();
172 } 172 }
173 173
174 if (do_liveness_analysis_) { 174 if (do_liveness_analysis_) {
175 // The liveness vector had bits for the liveness of the registers, and one 175 BytecodeLiveness& liveness = liveness_map_.InitializeLiveness(
176 // more bit for the liveness of the accumulator. 176 current_offset, bytecode_array()->register_count(), zone());
177 Liveness& liveness = liveness_map_.InitializeLiveness(
178 current_offset, bytecode_array()->register_count() + 1, zone());
179 177
180 UpdateOutLiveness(bytecode, *liveness.out, next_bytecode_in_liveness, 178 UpdateOutLiveness(bytecode, *liveness.out, next_bytecode_in_liveness,
181 iterator, liveness_map_); 179 iterator, liveness_map_);
182 liveness.in->CopyFrom(*liveness.out); 180 liveness.in->CopyFrom(*liveness.out);
183 UpdateInLiveness(bytecode, *liveness.in, iterator); 181 UpdateInLiveness(bytecode, *liveness.in, iterator);
184 182
185 next_bytecode_in_liveness = liveness.in; 183 next_bytecode_in_liveness = liveness.in;
186 } 184 }
187 } 185 }
188 186
(...skipping 28 matching lines...) Expand all
217 // outer-to-inner requirements. 215 // outer-to-inner requirements.
218 216
219 for (int loop_end_index : loop_end_index_queue_) { 217 for (int loop_end_index : loop_end_index_queue_) {
220 iterator.GoToIndex(loop_end_index); 218 iterator.GoToIndex(loop_end_index);
221 219
222 DCHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); 220 DCHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop);
223 221
224 int header_offset = iterator.GetJumpTargetOffset(); 222 int header_offset = iterator.GetJumpTargetOffset();
225 int end_offset = iterator.current_offset(); 223 int end_offset = iterator.current_offset();
226 224
227 Liveness& header_liveness = liveness_map_.GetLiveness(header_offset); 225 BytecodeLiveness& header_liveness =
228 Liveness& end_liveness = liveness_map_.GetLiveness(end_offset); 226 liveness_map_.GetLiveness(header_offset);
227 BytecodeLiveness& end_liveness = liveness_map_.GetLiveness(end_offset);
229 228
230 if (!end_liveness.out->UnionIsChanged(*header_liveness.in)) { 229 if (!end_liveness.out->UnionIsChanged(*header_liveness.in)) {
231 // Only update the loop body if the loop end liveness changed. 230 // Only update the loop body if the loop end liveness changed.
232 continue; 231 continue;
233 } 232 }
234 end_liveness.in->CopyFrom(*end_liveness.out); 233 end_liveness.in->CopyFrom(*end_liveness.out);
235 next_bytecode_in_liveness = end_liveness.in; 234 next_bytecode_in_liveness = end_liveness.in;
236 235
237 // Advance into the loop body. 236 // Advance into the loop body.
238 --iterator; 237 --iterator;
239 for (; iterator.current_offset() > header_offset; --iterator) { 238 for (; iterator.current_offset() > header_offset; --iterator) {
240 Bytecode bytecode = iterator.current_bytecode(); 239 Bytecode bytecode = iterator.current_bytecode();
241 240
242 int current_offset = iterator.current_offset(); 241 int current_offset = iterator.current_offset();
243 Liveness& liveness = liveness_map_.GetLiveness(current_offset); 242 BytecodeLiveness& liveness = liveness_map_.GetLiveness(current_offset);
244 243
245 UpdateOutLiveness(bytecode, *liveness.out, next_bytecode_in_liveness, 244 UpdateOutLiveness(bytecode, *liveness.out, next_bytecode_in_liveness,
246 iterator, liveness_map_); 245 iterator, liveness_map_);
247 liveness.in->CopyFrom(*liveness.out); 246 liveness.in->CopyFrom(*liveness.out);
248 UpdateInLiveness(bytecode, *liveness.in, iterator); 247 UpdateInLiveness(bytecode, *liveness.in, iterator);
249 248
250 next_bytecode_in_liveness = liveness.in; 249 next_bytecode_in_liveness = liveness.in;
251 } 250 }
252 // Now we are at the loop header. Since the in-liveness of the header 251 // Now we are at the loop header. Since the in-liveness of the header
253 // can't change, we need only to update the out-liveness. 252 // can't change, we need only to update the out-liveness.
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 305
307 return header_to_parent_.upper_bound(offset)->second; 306 return header_to_parent_.upper_bound(offset)->second;
308 } 307 }
309 308
310 int BytecodeAnalysis::GetParentLoopFor(int header_offset) const { 309 int BytecodeAnalysis::GetParentLoopFor(int header_offset) const {
311 DCHECK(IsLoopHeader(header_offset)); 310 DCHECK(IsLoopHeader(header_offset));
312 311
313 return header_to_parent_.find(header_offset)->second; 312 return header_to_parent_.find(header_offset)->second;
314 } 313 }
315 314
316 const BitVector* BytecodeAnalysis::GetInLivenessFor(int offset) const { 315 const BytecodeLivenessState* BytecodeAnalysis::GetInLivenessFor(
316 int offset) const {
317 if (!do_liveness_analysis_) return nullptr; 317 if (!do_liveness_analysis_) return nullptr;
318 318
319 return liveness_map_.GetInLiveness(offset); 319 return liveness_map_.GetInLiveness(offset);
320 } 320 }
321 321
322 const BitVector* BytecodeAnalysis::GetOutLivenessFor(int offset) const { 322 const BytecodeLivenessState* BytecodeAnalysis::GetOutLivenessFor(
323 int offset) const {
323 if (!do_liveness_analysis_) return nullptr; 324 if (!do_liveness_analysis_) return nullptr;
324 325
325 return liveness_map_.GetOutLiveness(offset); 326 return liveness_map_.GetOutLiveness(offset);
326 } 327 }
327 328
328 std::ostream& BytecodeAnalysis::PrintLivenessTo(std::ostream& os) const { 329 std::ostream& BytecodeAnalysis::PrintLivenessTo(std::ostream& os) const {
329 interpreter::BytecodeArrayIterator iterator(bytecode_array()); 330 interpreter::BytecodeArrayIterator iterator(bytecode_array());
330 331
331 for (; !iterator.done(); iterator.Advance()) { 332 for (; !iterator.done(); iterator.Advance()) {
332 int current_offset = iterator.current_offset(); 333 int current_offset = iterator.current_offset();
333 334
334 const BitVector* in_liveness = GetInLivenessFor(current_offset); 335 const BitVector& in_liveness =
335 const BitVector* out_liveness = GetOutLivenessFor(current_offset); 336 GetInLivenessFor(current_offset)->bit_vector();
337 const BitVector& out_liveness =
338 GetOutLivenessFor(current_offset)->bit_vector();
336 339
337 for (int i = 0; i < in_liveness->length(); ++i) { 340 for (int i = 0; i < in_liveness.length(); ++i) {
338 os << (in_liveness->Contains(i) ? "L" : "."); 341 os << (in_liveness.Contains(i) ? "L" : ".");
339 } 342 }
340 os << " -> "; 343 os << " -> ";
341 344
342 for (int i = 0; i < out_liveness->length(); ++i) { 345 for (int i = 0; i < out_liveness.length(); ++i) {
343 os << (out_liveness->Contains(i) ? "L" : "."); 346 os << (out_liveness.Contains(i) ? "L" : ".");
344 } 347 }
345 348
346 os << " | " << current_offset << ": "; 349 os << " | " << current_offset << ": ";
347 iterator.PrintTo(os) << std::endl; 350 iterator.PrintTo(os) << std::endl;
348 } 351 }
349 352
350 return os; 353 return os;
351 } 354 }
352 355
353 #if DEBUG 356 #if DEBUG
354 bool BytecodeAnalysis::LivenessIsValid() { 357 bool BytecodeAnalysis::LivenessIsValid() {
355 BytecodeArrayRandomIterator iterator(bytecode_array(), zone()); 358 BytecodeArrayRandomIterator iterator(bytecode_array(), zone());
356 359
357 BitVector previous_liveness(bytecode_array()->register_count() + 1, zone()); 360 BytecodeLivenessState previous_liveness(bytecode_array()->register_count(),
361 zone());
358 362
359 int invalid_offset = -1; 363 int invalid_offset = -1;
360 int which_invalid = -1; 364 int which_invalid = -1;
361 365
362 BitVector* next_bytecode_in_liveness = nullptr; 366 BytecodeLivenessState* next_bytecode_in_liveness = nullptr;
363 367
364 // Ensure that there are no liveness changes if we iterate one more time. 368 // Ensure that there are no liveness changes if we iterate one more time.
365 for (iterator.GoToEnd(); iterator.IsValid(); --iterator) { 369 for (iterator.GoToEnd(); iterator.IsValid(); --iterator) {
366 Bytecode bytecode = iterator.current_bytecode(); 370 Bytecode bytecode = iterator.current_bytecode();
367 371
368 int current_offset = iterator.current_offset(); 372 int current_offset = iterator.current_offset();
369 373
370 Liveness& liveness = liveness_map_.GetLiveness(current_offset); 374 BytecodeLiveness& liveness = liveness_map_.GetLiveness(current_offset);
371 375
372 previous_liveness.CopyFrom(*liveness.out); 376 previous_liveness.CopyFrom(*liveness.out);
373 377
374 UpdateOutLiveness(bytecode, *liveness.out, next_bytecode_in_liveness, 378 UpdateOutLiveness(bytecode, *liveness.out, next_bytecode_in_liveness,
375 iterator, liveness_map_); 379 iterator, liveness_map_);
376 // UpdateOutLiveness skips kJumpLoop, so we update it manually. 380 // UpdateOutLiveness skips kJumpLoop, so we update it manually.
377 if (bytecode == Bytecode::kJumpLoop) { 381 if (bytecode == Bytecode::kJumpLoop) {
378 int target_offset = iterator.GetJumpTargetOffset(); 382 int target_offset = iterator.GetJumpTargetOffset();
379 liveness.out->Union(*liveness_map_.GetInLiveness(target_offset)); 383 liveness.out->Union(*liveness_map_.GetInLiveness(target_offset));
380 } 384 }
(...skipping 26 matching lines...) Expand all
407 OFStream of(stderr); 411 OFStream of(stderr);
408 of << "Invalid liveness:" << std::endl; 412 of << "Invalid liveness:" << std::endl;
409 413
410 // Dump the bytecode, annotated with the liveness and marking loops. 414 // Dump the bytecode, annotated with the liveness and marking loops.
411 415
412 int loop_indent = 0; 416 int loop_indent = 0;
413 417
414 BytecodeArrayIterator forward_iterator(bytecode_array()); 418 BytecodeArrayIterator forward_iterator(bytecode_array());
415 for (; !forward_iterator.done(); forward_iterator.Advance()) { 419 for (; !forward_iterator.done(); forward_iterator.Advance()) {
416 int current_offset = forward_iterator.current_offset(); 420 int current_offset = forward_iterator.current_offset();
417 BitVector* in_liveness = liveness_map_.GetInLiveness(current_offset); 421 const BitVector& in_liveness =
418 BitVector* out_liveness = liveness_map_.GetOutLiveness(current_offset); 422 GetInLivenessFor(current_offset)->bit_vector();
423 const BitVector& out_liveness =
424 GetOutLivenessFor(current_offset)->bit_vector();
419 425
420 for (int i = 0; i < in_liveness->length(); ++i) { 426 for (int i = 0; i < in_liveness.length(); ++i) {
421 of << (in_liveness->Contains(i) ? 'L' : '.'); 427 of << (in_liveness.Contains(i) ? 'L' : '.');
422 } 428 }
423 429
424 of << " | "; 430 of << " | ";
425 431
426 for (int i = 0; i < out_liveness->length(); ++i) { 432 for (int i = 0; i < out_liveness.length(); ++i) {
427 of << (out_liveness->Contains(i) ? 'L' : '.'); 433 of << (out_liveness.Contains(i) ? 'L' : '.');
428 } 434 }
429 435
430 of << " : " << current_offset << " : "; 436 of << " : " << current_offset << " : ";
431 437
432 // Draw loop back edges by indentin everything between loop headers and 438 // Draw loop back edges by indentin everything between loop headers and
433 // jump loop instructions. 439 // jump loop instructions.
434 if (forward_iterator.current_bytecode() == Bytecode::kJumpLoop) { 440 if (forward_iterator.current_bytecode() == Bytecode::kJumpLoop) {
435 loop_indent--; 441 loop_indent--;
436 } 442 }
437 for (int i = 0; i < loop_indent; ++i) { 443 for (int i = 0; i < loop_indent; ++i) {
438 of << " | "; 444 of << " | ";
439 } 445 }
440 if (forward_iterator.current_bytecode() == Bytecode::kJumpLoop) { 446 if (forward_iterator.current_bytecode() == Bytecode::kJumpLoop) {
441 of << " `-" << current_offset; 447 of << " `-" << current_offset;
442 } else if (IsLoopHeader(current_offset)) { 448 } else if (IsLoopHeader(current_offset)) {
443 of << " .>" << current_offset; 449 of << " .>" << current_offset;
444 loop_indent++; 450 loop_indent++;
445 } 451 }
446 forward_iterator.PrintTo(of) << std::endl; 452 forward_iterator.PrintTo(of) << std::endl;
447 453
448 if (current_offset == invalid_offset) { 454 if (current_offset == invalid_offset) {
449 // Underline the invalid liveness. 455 // Underline the invalid liveness.
450 if (which_invalid == 0) { 456 if (which_invalid == 0) {
451 for (int i = 0; i < in_liveness->length(); ++i) { 457 for (int i = 0; i < in_liveness.length(); ++i) {
452 of << '^'; 458 of << '^';
453 } 459 }
454 } else { 460 } else {
455 for (int i = 0; i < in_liveness->length() + 3; ++i) { 461 for (int i = 0; i < in_liveness.length() + 3; ++i) {
456 of << ' '; 462 of << ' ';
457 } 463 }
458 for (int i = 0; i < out_liveness->length(); ++i) { 464 for (int i = 0; i < out_liveness.length(); ++i) {
459 of << '^'; 465 of << '^';
460 } 466 }
461 } 467 }
462 468
463 // Make sure to draw the loop indentation marks on this additional line. 469 // Make sure to draw the loop indentation marks on this additional line.
464 of << " : " << current_offset << " : "; 470 of << " : " << current_offset << " : ";
465 for (int i = 0; i < loop_indent; ++i) { 471 for (int i = 0; i < loop_indent; ++i) {
466 of << " | "; 472 of << " | ";
467 } 473 }
468 474
469 of << std::endl; 475 of << std::endl;
470 } 476 }
471 } 477 }
472 } 478 }
473 479
474 return invalid_offset == -1; 480 return invalid_offset == -1;
475 } 481 }
476 #endif 482 #endif
477 483
478 } // namespace compiler 484 } // namespace compiler
479 } // namespace internal 485 } // namespace internal
480 } // namespace v8 486 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/bytecode-analysis.h ('k') | src/compiler/bytecode-graph-builder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698