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/interpreter/bytecode-register-optimizer.cc

Issue 2351763002: [Interpreter] Optimize BytecodeArrayBuilder and BytecodeArrayWriter. (Closed)
Patch Set: [Interpreter] Optimize BytecodeArrayBuilder and BytecodeArrayWriter. Created 4 years, 3 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
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/interpreter/bytecode-register-optimizer.h" 5 #include "src/interpreter/bytecode-register-optimizer.h"
6 6
7 namespace v8 { 7 namespace v8 {
8 namespace internal { 8 namespace internal {
9 namespace interpreter { 9 namespace interpreter {
10 10
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 BytecodeRegisterOptimizer::RegisterInfo* 167 BytecodeRegisterOptimizer::RegisterInfo*
168 BytecodeRegisterOptimizer::RegisterInfo::GetEquivalent() { 168 BytecodeRegisterOptimizer::RegisterInfo::GetEquivalent() {
169 return next_; 169 return next_;
170 } 170 }
171 171
172 BytecodeRegisterOptimizer::BytecodeRegisterOptimizer( 172 BytecodeRegisterOptimizer::BytecodeRegisterOptimizer(
173 Zone* zone, TemporaryRegisterAllocator* register_allocator, 173 Zone* zone, TemporaryRegisterAllocator* register_allocator,
174 int parameter_count, BytecodePipelineStage* next_stage) 174 int parameter_count, BytecodePipelineStage* next_stage)
175 : accumulator_(Register::virtual_accumulator()), 175 : accumulator_(Register::virtual_accumulator()),
176 temporary_base_(register_allocator->allocation_base()), 176 temporary_base_(register_allocator->allocation_base()),
177 max_register_index_(register_allocator->allocation_base() - 1),
177 register_info_table_(zone), 178 register_info_table_(zone),
178 equivalence_id_(0), 179 equivalence_id_(0),
179 next_stage_(next_stage), 180 next_stage_(next_stage),
180 flush_required_(false), 181 flush_required_(false),
181 zone_(zone) { 182 zone_(zone) {
182 register_allocator->set_observer(this); 183 register_allocator->set_observer(this);
183 184
184 // Calculate offset so register index values can be mapped into 185 // Calculate offset so register index values can be mapped into
185 // a vector of register metadata. 186 // a vector of register metadata.
186 if (parameter_count != 0) { 187 if (parameter_count != 0) {
(...skipping 14 matching lines...) Expand all
201 RegisterFromRegisterInfoTableIndex(i), NextEquivalenceId(), true); 202 RegisterFromRegisterInfoTableIndex(i), NextEquivalenceId(), true);
202 DCHECK_EQ(register_info_table_[i]->register_value().index(), 203 DCHECK_EQ(register_info_table_[i]->register_value().index(),
203 RegisterFromRegisterInfoTableIndex(i).index()); 204 RegisterFromRegisterInfoTableIndex(i).index());
204 } 205 }
205 accumulator_info_ = GetRegisterInfo(accumulator_); 206 accumulator_info_ = GetRegisterInfo(accumulator_);
206 DCHECK(accumulator_info_->register_value() == accumulator_); 207 DCHECK(accumulator_info_->register_value() == accumulator_);
207 } 208 }
208 209
209 // override 210 // override
210 Handle<BytecodeArray> BytecodeRegisterOptimizer::ToBytecodeArray( 211 Handle<BytecodeArray> BytecodeRegisterOptimizer::ToBytecodeArray(
211 Isolate* isolate, int fixed_register_count, int parameter_count, 212 Isolate* isolate, int register_count, int parameter_count,
212 Handle<FixedArray> handler_table) { 213 Handle<FixedArray> handler_table) {
213 FlushState(); 214 FlushState();
214 return next_stage_->ToBytecodeArray(isolate, fixed_register_count, 215 return next_stage_->ToBytecodeArray(isolate, max_register_index_ + 1,
215 parameter_count, handler_table); 216 parameter_count, handler_table);
216 } 217 }
217 218
218 // override 219 // override
219 void BytecodeRegisterOptimizer::Write(BytecodeNode* node) { 220 void BytecodeRegisterOptimizer::Write(BytecodeNode* node) {
221 DCHECK(!Bytecodes::IsJump(node->bytecode()));
mythria 2016/09/21 08:12:45 May be a comment saying jumps are handled by Write
rmcilroy 2016/09/21 14:12:34 Done.
220 // 222 //
221 // Transfers with observable registers as the destination will be 223 // Transfers with observable registers as the destination will be
222 // immediately materialized so the source position information will 224 // immediately materialized so the source position information will
223 // be ordered correctly. 225 // be ordered correctly.
224 // 226 //
225 // Transfers without observable destination registers will initially 227 // Transfers without observable destination registers will initially
226 // be emitted as Nop's with the source position. They may, or may 228 // be emitted as Nop's with the source position. They may, or may
227 // not, be materialized by the optimizer. However, the source 229 // not, be materialized by the optimizer. However, the source
228 // position is not lost and being attached to a Nop is fine as the 230 // position is not lost and being attached to a Nop is fine as the
229 // destination register is not observable in the debugger. 231 // destination register is not observable in the debugger.
230 // 232 //
231 switch (node->bytecode()) { 233 switch (node->bytecode()) {
232 case Bytecode::kLdar: { 234 case Bytecode::kLdar: {
233 DoLdar(node); 235 DoLdar(node);
234 return; 236 return;
235 } 237 }
236 case Bytecode::kStar: { 238 case Bytecode::kStar: {
237 DoStar(node); 239 DoStar(node);
238 return; 240 return;
239 } 241 }
240 case Bytecode::kMov: { 242 case Bytecode::kMov: {
241 DoMov(node); 243 DoMov(node);
242 return; 244 return;
243 } 245 }
244 default: 246 default:
245 break; 247 break;
246 } 248 }
247 249
248 if (Bytecodes::IsJump(node->bytecode()) || 250 if (node->bytecode() == Bytecode::kDebugger ||
249 node->bytecode() == Bytecode::kDebugger ||
250 node->bytecode() == Bytecode::kSuspendGenerator) { 251 node->bytecode() == Bytecode::kSuspendGenerator) {
251 // All state must be flushed before emitting 252 // All state must be flushed before emitting
252 // - a jump (due to how bytecode offsets for jumps are evaluated), 253 // - a jump (due to how bytecode offsets for jumps are evaluated),
253 // - a call to the debugger (as it can manipulate locals and parameters), 254 // - a call to the debugger (as it can manipulate locals and parameters),
254 // - a generator suspend (as this involves saving all registers). 255 // - a generator suspend (as this involves saving all registers).
255 FlushState(); 256 FlushState();
256 } 257 }
257 258
258 PrepareOperands(node); 259 PrepareOperands(node);
259 WriteToNextStage(node); 260 next_stage_->Write(node);
260 } 261 }
261 262
262 // override 263 // override
263 void BytecodeRegisterOptimizer::WriteJump(BytecodeNode* node, 264 void BytecodeRegisterOptimizer::WriteJump(BytecodeNode* node,
264 BytecodeLabel* label) { 265 BytecodeLabel* label) {
265 FlushState(); 266 FlushState();
266 next_stage_->WriteJump(node, label); 267 next_stage_->WriteJump(node, label);
267 } 268 }
268 269
269 // override 270 // override
(...skipping 29 matching lines...) Expand all
299 OutputRegisterTransfer(reg_info, equivalent); 300 OutputRegisterTransfer(reg_info, equivalent);
300 } 301 }
301 equivalent->MoveToNewEquivalenceSet(NextEquivalenceId(), true); 302 equivalent->MoveToNewEquivalenceSet(NextEquivalenceId(), true);
302 } 303 }
303 } 304 }
304 } 305 }
305 306
306 flush_required_ = false; 307 flush_required_ = false;
307 } 308 }
308 309
309 void BytecodeRegisterOptimizer::WriteToNextStage(BytecodeNode* node) const {
310 next_stage_->Write(node);
311 }
312
313 void BytecodeRegisterOptimizer::WriteToNextStage(
314 BytecodeNode* node, const BytecodeSourceInfo& source_info) const {
315 if (source_info.is_valid()) {
316 node->source_info().Clone(source_info);
317 }
318 next_stage_->Write(node);
319 }
320
321 void BytecodeRegisterOptimizer::OutputRegisterTransfer( 310 void BytecodeRegisterOptimizer::OutputRegisterTransfer(
322 RegisterInfo* input_info, RegisterInfo* output_info, 311 RegisterInfo* input_info, RegisterInfo* output_info,
323 const BytecodeSourceInfo& source_info) { 312 BytecodeSourceInfo* source_info) {
324 Register input = input_info->register_value(); 313 Register input = input_info->register_value();
325 Register output = output_info->register_value(); 314 Register output = output_info->register_value();
326 DCHECK_NE(input.index(), output.index()); 315 DCHECK_NE(input.index(), output.index());
327 316
328 if (input == accumulator_) { 317 if (input == accumulator_) {
329 uint32_t operand = static_cast<uint32_t>(output.ToOperand()); 318 uint32_t operand = static_cast<uint32_t>(output.ToOperand());
330 BytecodeNode node(Bytecode::kStar, operand); 319 BytecodeNode node(Bytecode::kStar, operand, source_info);
331 WriteToNextStage(&node, source_info); 320 next_stage_->Write(&node);
332 } else if (output == accumulator_) { 321 } else if (output == accumulator_) {
333 uint32_t operand = static_cast<uint32_t>(input.ToOperand()); 322 uint32_t operand = static_cast<uint32_t>(input.ToOperand());
334 BytecodeNode node(Bytecode::kLdar, operand); 323 BytecodeNode node(Bytecode::kLdar, operand, source_info);
335 WriteToNextStage(&node, source_info); 324 next_stage_->Write(&node);
336 } else { 325 } else {
337 uint32_t operand0 = static_cast<uint32_t>(input.ToOperand()); 326 uint32_t operand0 = static_cast<uint32_t>(input.ToOperand());
338 uint32_t operand1 = static_cast<uint32_t>(output.ToOperand()); 327 uint32_t operand1 = static_cast<uint32_t>(output.ToOperand());
339 BytecodeNode node(Bytecode::kMov, operand0, operand1); 328 BytecodeNode node(Bytecode::kMov, operand0, operand1, source_info);
340 WriteToNextStage(&node, source_info); 329 next_stage_->Write(&node);
330 }
331 if (output != accumulator_) {
332 max_register_index_ = std::max(max_register_index_, output.index());
341 } 333 }
342 output_info->set_materialized(true); 334 output_info->set_materialized(true);
343 } 335 }
344 336
345 void BytecodeRegisterOptimizer::CreateMaterializedEquivalent( 337 void BytecodeRegisterOptimizer::CreateMaterializedEquivalent(
346 RegisterInfo* info) { 338 RegisterInfo* info) {
347 DCHECK(info->materialized()); 339 DCHECK(info->materialized());
348 RegisterInfo* unmaterialized = info->GetEquivalentToMaterialize(); 340 RegisterInfo* unmaterialized = info->GetEquivalentToMaterialize();
349 if (unmaterialized) { 341 if (unmaterialized) {
350 OutputRegisterTransfer(info, unmaterialized); 342 OutputRegisterTransfer(info, unmaterialized);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 void BytecodeRegisterOptimizer::AddToEquivalenceSet( 374 void BytecodeRegisterOptimizer::AddToEquivalenceSet(
383 RegisterInfo* set_member, RegisterInfo* non_set_member) { 375 RegisterInfo* set_member, RegisterInfo* non_set_member) {
384 non_set_member->AddToEquivalenceSetOf(set_member); 376 non_set_member->AddToEquivalenceSetOf(set_member);
385 // Flushing is only required when two or more registers are placed 377 // Flushing is only required when two or more registers are placed
386 // in the same equivalence set. 378 // in the same equivalence set.
387 flush_required_ = true; 379 flush_required_ = true;
388 } 380 }
389 381
390 void BytecodeRegisterOptimizer::RegisterTransfer( 382 void BytecodeRegisterOptimizer::RegisterTransfer(
391 RegisterInfo* input_info, RegisterInfo* output_info, 383 RegisterInfo* input_info, RegisterInfo* output_info,
392 const BytecodeSourceInfo& source_info) { 384 BytecodeSourceInfo* source_info) {
393 // Materialize an alternate in the equivalence set that 385 // Materialize an alternate in the equivalence set that
394 // |output_info| is leaving. 386 // |output_info| is leaving.
395 if (output_info->materialized()) { 387 if (output_info->materialized()) {
396 CreateMaterializedEquivalent(output_info); 388 CreateMaterializedEquivalent(output_info);
397 } 389 }
398 390
399 // Add |output_info| to new equivalence set. 391 // Add |output_info| to new equivalence set.
400 if (!output_info->IsInSameEquivalenceSet(input_info)) { 392 if (!output_info->IsInSameEquivalenceSet(input_info)) {
401 AddToEquivalenceSet(input_info, output_info); 393 AddToEquivalenceSet(input_info, output_info);
402 } 394 }
403 395
404 bool output_is_observable = 396 bool output_is_observable =
405 RegisterIsObservable(output_info->register_value()); 397 RegisterIsObservable(output_info->register_value());
406 if (output_is_observable) { 398 if (output_is_observable) {
407 // Force store to be emitted when register is observable. 399 // Force store to be emitted when register is observable.
408 output_info->set_materialized(false); 400 output_info->set_materialized(false);
409 RegisterInfo* materialized_info = input_info->GetMaterializedEquivalent(); 401 RegisterInfo* materialized_info = input_info->GetMaterializedEquivalent();
410 OutputRegisterTransfer(materialized_info, output_info, source_info); 402 OutputRegisterTransfer(materialized_info, output_info, source_info);
411 } else if (source_info.is_valid()) { 403 } else if (source_info->is_valid()) {
412 // Emit a placeholder nop to maintain source position info. 404 // Emit a placeholder nop to maintain source position info.
413 EmitNopForSourceInfo(source_info); 405 EmitNopForSourceInfo(source_info);
414 } 406 }
415 } 407 }
416 408
417 void BytecodeRegisterOptimizer::EmitNopForSourceInfo( 409 void BytecodeRegisterOptimizer::EmitNopForSourceInfo(
418 const BytecodeSourceInfo& source_info) const { 410 BytecodeSourceInfo* source_info) const {
419 DCHECK(source_info.is_valid()); 411 DCHECK(source_info->is_valid());
420 BytecodeNode nop(Bytecode::kNop); 412 BytecodeNode nop(Bytecode::kNop, source_info);
421 nop.source_info().Clone(source_info); 413 next_stage_->Write(&nop);
422 WriteToNextStage(&nop);
423 } 414 }
424 415
425 void BytecodeRegisterOptimizer::DoLdar(const BytecodeNode* const node) { 416 void BytecodeRegisterOptimizer::DoLdar(BytecodeNode* node) {
426 Register input = GetRegisterInputOperand( 417 Register input = GetRegisterInputOperand(
427 0, node->bytecode(), node->operands(), node->operand_count()); 418 0, node->bytecode(), node->operands(), node->operand_count());
428 RegisterInfo* input_info = GetRegisterInfo(input); 419 RegisterInfo* input_info = GetRegisterInfo(input);
429 RegisterTransfer(input_info, accumulator_info_, node->source_info()); 420 RegisterTransfer(input_info, accumulator_info_, node->source_info_ptr());
430 } 421 }
431 422
432 void BytecodeRegisterOptimizer::DoMov(const BytecodeNode* const node) { 423 void BytecodeRegisterOptimizer::DoMov(BytecodeNode* node) {
433 Register input = GetRegisterInputOperand( 424 Register input = GetRegisterInputOperand(
434 0, node->bytecode(), node->operands(), node->operand_count()); 425 0, node->bytecode(), node->operands(), node->operand_count());
435 RegisterInfo* input_info = GetRegisterInfo(input); 426 RegisterInfo* input_info = GetRegisterInfo(input);
436 Register output = GetRegisterOutputOperand( 427 Register output = GetRegisterOutputOperand(
437 1, node->bytecode(), node->operands(), node->operand_count()); 428 1, node->bytecode(), node->operands(), node->operand_count());
438 RegisterInfo* output_info = GetOrCreateRegisterInfo(output); 429 RegisterInfo* output_info = GetOrCreateRegisterInfo(output);
439 RegisterTransfer(input_info, output_info, node->source_info()); 430 RegisterTransfer(input_info, output_info, node->source_info_ptr());
440 } 431 }
441 432
442 void BytecodeRegisterOptimizer::DoStar(const BytecodeNode* const node) { 433 void BytecodeRegisterOptimizer::DoStar(BytecodeNode* node) {
443 Register output = GetRegisterOutputOperand( 434 Register output = GetRegisterOutputOperand(
444 0, node->bytecode(), node->operands(), node->operand_count()); 435 0, node->bytecode(), node->operands(), node->operand_count());
445 RegisterInfo* output_info = GetOrCreateRegisterInfo(output); 436 RegisterInfo* output_info = GetOrCreateRegisterInfo(output);
446 RegisterTransfer(accumulator_info_, output_info, node->source_info()); 437 RegisterTransfer(accumulator_info_, output_info, node->source_info_ptr());
447 } 438 }
448 439
449 void BytecodeRegisterOptimizer::PrepareRegisterOutputOperand( 440 void BytecodeRegisterOptimizer::PrepareRegisterOutputOperand(
450 RegisterInfo* reg_info) { 441 RegisterInfo* reg_info) {
451 if (reg_info->materialized()) { 442 if (reg_info->materialized()) {
452 CreateMaterializedEquivalent(reg_info); 443 CreateMaterializedEquivalent(reg_info);
453 } 444 }
445 max_register_index_ =
446 std::max(max_register_index_, reg_info->register_value().index());
454 reg_info->MoveToNewEquivalenceSet(NextEquivalenceId(), true); 447 reg_info->MoveToNewEquivalenceSet(NextEquivalenceId(), true);
455 } 448 }
456 449
457 void BytecodeRegisterOptimizer::PrepareRegisterRangeOutputOperand( 450 void BytecodeRegisterOptimizer::PrepareRegisterRangeOutputOperand(
458 Register start, int count) { 451 Register start, int count) {
459 for (int i = 0; i < count; ++i) { 452 for (int i = 0; i < count; ++i) {
460 Register reg(start.index() + i); 453 Register reg(start.index() + i);
461 RegisterInfo* reg_info = GetOrCreateRegisterInfo(reg); 454 RegisterInfo* reg_info = GetOrCreateRegisterInfo(reg);
462 PrepareRegisterOutputOperand(reg_info); 455 PrepareRegisterOutputOperand(reg_info);
463 } 456 }
(...skipping 10 matching lines...) Expand all
474 } else { 467 } else {
475 RegisterInfo* equivalent_info = 468 RegisterInfo* equivalent_info =
476 GetMaterializedEquivalentNotAccumulator(reg_info); 469 GetMaterializedEquivalentNotAccumulator(reg_info);
477 return equivalent_info->register_value(); 470 return equivalent_info->register_value();
478 } 471 }
479 } 472 }
480 473
481 void BytecodeRegisterOptimizer::PrepareRegisterInputOperand( 474 void BytecodeRegisterOptimizer::PrepareRegisterInputOperand(
482 BytecodeNode* const node, Register reg, int operand_index) { 475 BytecodeNode* const node, Register reg, int operand_index) {
483 Register equivalent = GetEquivalentRegisterForInputOperand(reg); 476 Register equivalent = GetEquivalentRegisterForInputOperand(reg);
484 node->operands()[operand_index] = 477 node->UpdateOperand(operand_index,
485 static_cast<uint32_t>(equivalent.ToOperand()); 478 static_cast<uint32_t>(equivalent.ToOperand()));
486 } 479 }
487 480
488 void BytecodeRegisterOptimizer::PrepareRegisterRangeInputOperand(Register start, 481 void BytecodeRegisterOptimizer::PrepareRegisterRangeInputOperand(Register start,
489 int count) { 482 int count) {
490 for (int i = 0; i < count; ++i) { 483 for (int i = 0; i < count; ++i) {
491 Register current(start.index() + i); 484 Register current(start.index() + i);
492 RegisterInfo* input_info = GetRegisterInfo(current); 485 RegisterInfo* input_info = GetRegisterInfo(current);
493 Materialize(input_info); 486 Materialize(input_info);
494 } 487 }
495 } 488 }
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 if (info->materialized()) { 611 if (info->materialized()) {
619 CreateMaterializedEquivalent(info); 612 CreateMaterializedEquivalent(info);
620 } 613 }
621 info->MoveToNewEquivalenceSet(kInvalidEquivalenceId, false); 614 info->MoveToNewEquivalenceSet(kInvalidEquivalenceId, false);
622 } 615 }
623 } 616 }
624 617
625 } // namespace interpreter 618 } // namespace interpreter
626 } // namespace internal 619 } // namespace internal
627 } // namespace v8 620 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698