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 2541463002: [turbofan] Keep the next bytecode liveness when analysing (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 | « no previous file | no next file » | 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-reverse-iterator.h" 8 #include "src/interpreter/bytecode-array-reverse-iterator.h"
9 #include "src/objects-inl.h" 9 #include "src/objects-inl.h"
10 10
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 } 102 }
103 } 103 }
104 default: 104 default:
105 DCHECK(!Bytecodes::IsRegisterInputOperandType(operand_types[i])); 105 DCHECK(!Bytecodes::IsRegisterInputOperandType(operand_types[i]));
106 break; 106 break;
107 } 107 }
108 } 108 }
109 } 109 }
110 110
111 void UpdateOutLiveness(Bytecode bytecode, BitVector& out_liveness, 111 void UpdateOutLiveness(Bytecode bytecode, BitVector& out_liveness,
112 BitVector* next_bytecode_in_liveness,
112 const BytecodeArrayAccessor& accessor, 113 const BytecodeArrayAccessor& accessor,
113 const BytecodeLivenessMap& liveness_map) { 114 const BytecodeLivenessMap& liveness_map) {
114 int current_offset = accessor.current_offset(); 115 int current_offset = accessor.current_offset();
115 const Handle<BytecodeArray>& bytecode_array = accessor.bytecode_array(); 116 const Handle<BytecodeArray>& bytecode_array = accessor.bytecode_array();
116 117
117 // Update from jump target (if any). Skip loops, we update these manually in 118 // Update from jump target (if any). Skip loops, we update these manually in
118 // the liveness iterations. 119 // the liveness iterations.
119 if (Bytecodes::IsForwardJump(bytecode)) { 120 if (Bytecodes::IsForwardJump(bytecode)) {
120 int target_offset = accessor.GetJumpTargetOffset(); 121 int target_offset = accessor.GetJumpTargetOffset();
121 out_liveness.Union(*liveness_map.GetInLiveness(target_offset)); 122 out_liveness.Union(*liveness_map.GetInLiveness(target_offset));
122 } 123 }
123 124
124 // Update from next bytecode (unless this is an unconditional jump). 125 // Update from next bytecode (unless there isn't one or this is an
125 if (!Bytecodes::IsUnconditionalJump(bytecode)) { 126 // unconditional jump).
126 int next_offset = current_offset + accessor.current_bytecode_size(); 127 if (next_bytecode_in_liveness != nullptr &&
127 if (next_offset < bytecode_array->length()) { 128 !Bytecodes::IsUnconditionalJump(bytecode)) {
128 out_liveness.Union(*liveness_map.GetInLiveness(next_offset)); 129 out_liveness.Union(*next_bytecode_in_liveness);
129 }
130 } 130 }
131 131
132 // Update from exception handler (if any). 132 // Update from exception handler (if any).
133 if (!interpreter::Bytecodes::IsWithoutExternalSideEffects(bytecode)) { 133 if (!interpreter::Bytecodes::IsWithoutExternalSideEffects(bytecode)) {
134 int handler_context; 134 int handler_context;
135 // TODO(leszeks): We should look up this range only once per entry. 135 // TODO(leszeks): We should look up this range only once per entry.
136 HandlerTable* table = HandlerTable::cast(bytecode_array->handler_table()); 136 HandlerTable* table = HandlerTable::cast(bytecode_array->handler_table());
137 int handler_offset = 137 int handler_offset =
138 table->LookupRange(current_offset, &handler_context, nullptr); 138 table->LookupRange(current_offset, &handler_context, nullptr);
139 139
140 if (handler_offset != -1) { 140 if (handler_offset != -1) {
141 out_liveness.Union(*liveness_map.GetInLiveness(handler_offset)); 141 out_liveness.Union(*liveness_map.GetInLiveness(handler_offset));
142 out_liveness.Add(handler_context); 142 out_liveness.Add(handler_context);
143 } 143 }
144 } 144 }
145 } 145 }
146 146
147 } // namespace 147 } // namespace
148 148
149 void BytecodeAnalysis::Analyze() { 149 void BytecodeAnalysis::Analyze() {
150 loop_stack_.push(-1); 150 loop_stack_.push(-1);
151 151
152 BitVector* next_bytecode_in_liveness = nullptr;
153
152 // The last JumpLoop that we haven't done a guaranteed valid liveness pass 154 // The last JumpLoop that we haven't done a guaranteed valid liveness pass
153 // over. See the below wall of text for a more thorough explanation. 155 // over. See the below wall of text for a more thorough explanation.
154 int last_invalid_jumploop_offset = -1; 156 int last_invalid_jumploop_offset = -1;
155 157
156 BytecodeArrayReverseIterator iterator(bytecode_array(), zone()); 158 BytecodeArrayReverseIterator iterator(bytecode_array(), zone());
157 for (; !iterator.done(); iterator.Advance()) { 159 for (; !iterator.done(); iterator.Advance()) {
158 Bytecode bytecode = iterator.current_bytecode(); 160 Bytecode bytecode = iterator.current_bytecode();
159 int current_offset = iterator.current_offset(); 161 int current_offset = iterator.current_offset();
160 162
161 if (bytecode == Bytecode::kJumpLoop) { 163 if (bytecode == Bytecode::kJumpLoop) {
162 PushLoop(iterator.GetJumpTargetOffset(), current_offset); 164 PushLoop(iterator.GetJumpTargetOffset(), current_offset);
163 165
164 // Save the last offset so that we can do another pass later. 166 // Save the last offset so that we can do another pass later.
165 if (last_invalid_jumploop_offset == -1) { 167 if (last_invalid_jumploop_offset == -1) {
166 last_invalid_jumploop_offset = current_offset; 168 last_invalid_jumploop_offset = current_offset;
167 } 169 }
168 } else if (current_offset == loop_stack_.top()) { 170 } else if (current_offset == loop_stack_.top()) {
169 loop_stack_.pop(); 171 loop_stack_.pop();
170 } 172 }
171 173
172 if (do_liveness_analysis_) { 174 if (do_liveness_analysis_) {
173 // The liveness vector had bits for the liveness of the registers, and one 175 // The liveness vector had bits for the liveness of the registers, and one
174 // more bit for the liveness of the accumulator. 176 // more bit for the liveness of the accumulator.
175 Liveness& liveness = liveness_map_.InitializeLiveness( 177 Liveness& liveness = liveness_map_.InitializeLiveness(
176 current_offset, bytecode_array()->register_count() + 1, zone()); 178 current_offset, bytecode_array()->register_count() + 1, zone());
177 179
178 UpdateOutLiveness(bytecode, *liveness.out, iterator, liveness_map_); 180 UpdateOutLiveness(bytecode, *liveness.out, next_bytecode_in_liveness,
181 iterator, liveness_map_);
179 liveness.in->CopyFrom(*liveness.out); 182 liveness.in->CopyFrom(*liveness.out);
180 UpdateInLiveness(bytecode, *liveness.in, iterator); 183 UpdateInLiveness(bytecode, *liveness.in, iterator);
184
185 next_bytecode_in_liveness = liveness.in;
181 } 186 }
182 } 187 }
183 188
184 DCHECK_EQ(loop_stack_.size(), 1u); 189 DCHECK_EQ(loop_stack_.size(), 1u);
185 DCHECK_EQ(loop_stack_.top(), -1); 190 DCHECK_EQ(loop_stack_.top(), -1);
186 191
187 if (!do_liveness_analysis_) return; 192 if (!do_liveness_analysis_) return;
188 193
189 // At this point, every bytecode has a valid in and out liveness, except for 194 // At this point, every bytecode has a valid in and out liveness, except for
190 // propagating liveness across back edges (i.e. JumpLoop). Subsequent liveness 195 // propagating liveness across back edges (i.e. JumpLoop). Subsequent liveness
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 234
230 int header_offset = iterator.GetJumpTargetOffset(); 235 int header_offset = iterator.GetJumpTargetOffset();
231 int end_offset = iterator.current_offset(); 236 int end_offset = iterator.current_offset();
232 237
233 Liveness& header_liveness = liveness_map_.GetLiveness(header_offset); 238 Liveness& header_liveness = liveness_map_.GetLiveness(header_offset);
234 Liveness& end_liveness = liveness_map_.GetLiveness(end_offset); 239 Liveness& end_liveness = liveness_map_.GetLiveness(end_offset);
235 240
236 if (end_liveness.out->UnionIsChanged(*header_liveness.in)) { 241 if (end_liveness.out->UnionIsChanged(*header_liveness.in)) {
237 // Only update the loop body if the loop end liveness changed. 242 // Only update the loop body if the loop end liveness changed.
238 end_liveness.in->CopyFrom(*end_liveness.out); 243 end_liveness.in->CopyFrom(*end_liveness.out);
244 next_bytecode_in_liveness = end_liveness.in;
239 245
240 // Advance into the loop body. 246 // Advance into the loop body.
241 iterator.Advance(); 247 iterator.Advance();
242 for (; iterator.current_offset() > header_offset; iterator.Advance()) { 248 for (; iterator.current_offset() > header_offset; iterator.Advance()) {
243 bytecode = iterator.current_bytecode(); 249 bytecode = iterator.current_bytecode();
244 if (bytecode == Bytecode::kJumpLoop) { 250 if (bytecode == Bytecode::kJumpLoop) {
245 // We can't validate this loop at the moment because we can't 251 // We can't validate this loop at the moment because we can't
246 // guarantee that its header is valid yet. Save it for later. 252 // guarantee that its header is valid yet. Save it for later.
247 if (last_invalid_jumploop_offset == -1) { 253 if (last_invalid_jumploop_offset == -1) {
248 last_invalid_jumploop_offset = iterator.current_offset(); 254 last_invalid_jumploop_offset = iterator.current_offset();
249 } 255 }
250 } 256 }
251 257
252 int current_offset = iterator.current_offset(); 258 int current_offset = iterator.current_offset();
253 Liveness& liveness = liveness_map_.GetLiveness(current_offset); 259 Liveness& liveness = liveness_map_.GetLiveness(current_offset);
254 260
255 UpdateOutLiveness(bytecode, *liveness.out, iterator, liveness_map_); 261 UpdateOutLiveness(bytecode, *liveness.out, next_bytecode_in_liveness,
262 iterator, liveness_map_);
256 liveness.in->CopyFrom(*liveness.out); 263 liveness.in->CopyFrom(*liveness.out);
257 UpdateInLiveness(bytecode, *liveness.in, iterator); 264 UpdateInLiveness(bytecode, *liveness.in, iterator);
265
266 next_bytecode_in_liveness = liveness.in;
258 } 267 }
259 // Now we are at the loop header. Since the in-liveness of the header 268 // Now we are at the loop header. Since the in-liveness of the header
260 // can't change, we need only to update the out-liveness. 269 // can't change, we need only to update the out-liveness.
261 bytecode = iterator.current_bytecode(); 270 bytecode = iterator.current_bytecode();
262 UpdateOutLiveness(bytecode, *header_liveness.out, iterator, 271 UpdateOutLiveness(bytecode, *header_liveness.out,
263 liveness_map_); 272 next_bytecode_in_liveness, iterator, liveness_map_);
264 } 273 }
265 274
266 // Keep the iterator going so that we can find other loops. 275 // Keep the iterator going so that we can find other loops.
267 } 276 }
268 } 277 }
269 278
270 DCHECK(LivenessIsValid()); 279 DCHECK(LivenessIsValid());
271 } 280 }
272 281
273 void BytecodeAnalysis::PushLoop(int loop_header, int loop_end) { 282 void BytecodeAnalysis::PushLoop(int loop_header, int loop_end) {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 373
365 #if DEBUG 374 #if DEBUG
366 bool BytecodeAnalysis::LivenessIsValid() { 375 bool BytecodeAnalysis::LivenessIsValid() {
367 BytecodeArrayReverseIterator iterator(bytecode_array(), zone()); 376 BytecodeArrayReverseIterator iterator(bytecode_array(), zone());
368 377
369 BitVector previous_liveness(bytecode_array()->register_count() + 1, zone()); 378 BitVector previous_liveness(bytecode_array()->register_count() + 1, zone());
370 379
371 int invalid_offset = -1; 380 int invalid_offset = -1;
372 int which_invalid = -1; 381 int which_invalid = -1;
373 382
383 BitVector* next_bytecode_in_liveness = nullptr;
384
374 // Ensure that there are no liveness changes if we iterate one more time. 385 // Ensure that there are no liveness changes if we iterate one more time.
375 for (iterator.Reset(); !iterator.done(); iterator.Advance()) { 386 for (iterator.Reset(); !iterator.done(); iterator.Advance()) {
376 Bytecode bytecode = iterator.current_bytecode(); 387 Bytecode bytecode = iterator.current_bytecode();
377 388
378 int current_offset = iterator.current_offset(); 389 int current_offset = iterator.current_offset();
379 390
380 Liveness& liveness = liveness_map_.GetLiveness(current_offset); 391 Liveness& liveness = liveness_map_.GetLiveness(current_offset);
381 392
382 previous_liveness.CopyFrom(*liveness.out); 393 previous_liveness.CopyFrom(*liveness.out);
383 394
384 UpdateOutLiveness(bytecode, *liveness.out, iterator, liveness_map_); 395 UpdateOutLiveness(bytecode, *liveness.out, next_bytecode_in_liveness,
396 iterator, liveness_map_);
385 // UpdateOutLiveness skips kJumpLoop, so we update it manually. 397 // UpdateOutLiveness skips kJumpLoop, so we update it manually.
386 if (bytecode == Bytecode::kJumpLoop) { 398 if (bytecode == Bytecode::kJumpLoop) {
387 int target_offset = iterator.GetJumpTargetOffset(); 399 int target_offset = iterator.GetJumpTargetOffset();
388 liveness.out->Union(*liveness_map_.GetInLiveness(target_offset)); 400 liveness.out->Union(*liveness_map_.GetInLiveness(target_offset));
389 } 401 }
390 402
391 if (!liveness.out->Equals(previous_liveness)) { 403 if (!liveness.out->Equals(previous_liveness)) {
392 // Reset the invalid liveness. 404 // Reset the invalid liveness.
393 liveness.out->CopyFrom(previous_liveness); 405 liveness.out->CopyFrom(previous_liveness);
394 invalid_offset = current_offset; 406 invalid_offset = current_offset;
395 which_invalid = 1; 407 which_invalid = 1;
396 break; 408 break;
397 } 409 }
398 410
399 previous_liveness.CopyFrom(*liveness.in); 411 previous_liveness.CopyFrom(*liveness.in);
400 412
401 liveness.in->CopyFrom(*liveness.out); 413 liveness.in->CopyFrom(*liveness.out);
402 UpdateInLiveness(bytecode, *liveness.in, iterator); 414 UpdateInLiveness(bytecode, *liveness.in, iterator);
403 415
404 if (!liveness.in->Equals(previous_liveness)) { 416 if (!liveness.in->Equals(previous_liveness)) {
405 // Reset the invalid liveness. 417 // Reset the invalid liveness.
406 liveness.in->CopyFrom(previous_liveness); 418 liveness.in->CopyFrom(previous_liveness);
407 invalid_offset = current_offset; 419 invalid_offset = current_offset;
408 which_invalid = 0; 420 which_invalid = 0;
409 break; 421 break;
410 } 422 }
423
424 next_bytecode_in_liveness = liveness.in;
411 } 425 }
412 426
413 if (invalid_offset != -1) { 427 if (invalid_offset != -1) {
414 OFStream of(stderr); 428 OFStream of(stderr);
415 of << "Invalid liveness:" << std::endl; 429 of << "Invalid liveness:" << std::endl;
416 430
417 // Dump the bytecode, annotated with the liveness and marking loops. 431 // Dump the bytecode, annotated with the liveness and marking loops.
418 432
419 int loop_indent = 0; 433 int loop_indent = 0;
420 434
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 } 492 }
479 } 493 }
480 494
481 return invalid_offset == -1; 495 return invalid_offset == -1;
482 } 496 }
483 #endif 497 #endif
484 498
485 } // namespace compiler 499 } // namespace compiler
486 } // namespace internal 500 } // namespace internal
487 } // namespace v8 501 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698