OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |