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

Side by Side Diff: runtime/vm/flow_graph_compiler.cc

Issue 10696151: Skeleton of a linear scan register allocator. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 5 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_XXX. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_XXX.
6 6
7 #include "vm/flow_graph_compiler.h" 7 #include "vm/flow_graph_compiler.h"
8 8
9 #include "vm/dart_entry.h" 9 #include "vm/dart_entry.h"
10 #include "vm/debugger.h" 10 #include "vm/debugger.h"
(...skipping 15 matching lines...) Expand all
26 DECLARE_FLAG(bool, report_usage_count); 26 DECLARE_FLAG(bool, report_usage_count);
27 DECLARE_FLAG(bool, trace_functions); 27 DECLARE_FLAG(bool, trace_functions);
28 DECLARE_FLAG(int, optimization_counter_threshold); 28 DECLARE_FLAG(int, optimization_counter_threshold);
29 29
30 30
31 FlowGraphCompiler::FlowGraphCompiler( 31 FlowGraphCompiler::FlowGraphCompiler(
32 Assembler* assembler, 32 Assembler* assembler,
33 const ParsedFunction& parsed_function, 33 const ParsedFunction& parsed_function,
34 const GrowableArray<BlockEntryInstr*>& block_order, 34 const GrowableArray<BlockEntryInstr*>& block_order,
35 bool is_optimizing, 35 bool is_optimizing,
36 bool is_ssa,
36 bool is_leaf) 37 bool is_leaf)
37 : assembler_(assembler), 38 : assembler_(assembler),
38 parsed_function_(parsed_function), 39 parsed_function_(parsed_function),
39 block_order_(block_order), 40 block_order_(block_order),
40 current_block_(NULL), 41 current_block_(NULL),
41 exception_handlers_list_(NULL), 42 exception_handlers_list_(NULL),
42 pc_descriptors_list_(NULL), 43 pc_descriptors_list_(NULL),
43 stackmap_builder_(NULL), 44 stackmap_builder_(NULL),
44 block_info_(block_order.length()), 45 block_info_(block_order.length()),
45 deopt_stubs_(), 46 deopt_stubs_(),
46 is_optimizing_(is_optimizing), 47 is_optimizing_(is_optimizing),
48 is_ssa_(is_ssa),
47 is_dart_leaf_(is_leaf), 49 is_dart_leaf_(is_leaf),
48 bool_true_(Bool::ZoneHandle(Bool::True())), 50 bool_true_(Bool::ZoneHandle(Bool::True())),
49 bool_false_(Bool::ZoneHandle(Bool::False())), 51 bool_false_(Bool::ZoneHandle(Bool::False())),
50 double_class_(Class::ZoneHandle( 52 double_class_(Class::ZoneHandle(
51 Isolate::Current()->object_store()->double_class())), 53 Isolate::Current()->object_store()->double_class())),
52 frame_register_allocator_(this, is_optimizing) { 54 frame_register_allocator_(this, is_optimizing, is_ssa),
55 parallel_move_resolver_(this) {
53 ASSERT(assembler != NULL); 56 ASSERT(assembler != NULL);
srdjan 2012/07/10 23:27:54 You could also ASSERT(is_optimizing_ || !is_ssa_);
Vyacheslav Egorov (Google) 2012/07/11 13:27:58 Done.
54 } 57 }
55 58
56 59
57 FlowGraphCompiler::~FlowGraphCompiler() { 60 FlowGraphCompiler::~FlowGraphCompiler() {
58 // BlockInfos are zone-allocated, so their destructors are not called. 61 // BlockInfos are zone-allocated, so their destructors are not called.
59 // Verify the labels explicitly here. 62 // Verify the labels explicitly here.
60 for (int i = 0; i < block_info_.length(); ++i) { 63 for (int i = 0; i < block_info_.length(); ++i) {
61 ASSERT(!block_info_[i]->label.IsLinked()); 64 ASSERT(!block_info_[i]->label.IsLinked());
62 ASSERT(!block_info_[i]->label.HasNear()); 65 ASSERT(!block_info_[i]->label.HasNear());
63 } 66 }
(...skipping 30 matching lines...) Expand all
94 assembler()->Comment("B%d", i); 97 assembler()->Comment("B%d", i);
95 // Compile the block entry. 98 // Compile the block entry.
96 BlockEntryInstr* entry = block_order()[i]; 99 BlockEntryInstr* entry = block_order()[i];
97 set_current_block(entry); 100 set_current_block(entry);
98 entry->PrepareEntry(this); 101 entry->PrepareEntry(this);
99 // Compile all successors until an exit, branch, or a block entry. 102 // Compile all successors until an exit, branch, or a block entry.
100 Instruction* instr = entry; 103 Instruction* instr = entry;
101 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 104 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
102 instr = it.Current(); 105 instr = it.Current();
103 if (FLAG_code_comments) EmitComment(instr); 106 if (FLAG_code_comments) EmitComment(instr);
104 ASSERT(instr->locs() != NULL); 107 if (instr->IsParallelMove()) {
105 EmitInstructionPrologue(instr); 108 parallel_move_resolver_.EmitNativeCode(instr->AsParallelMove());
106 instr->EmitNativeCode(this); 109 } else {
110 ASSERT(instr->locs() != NULL);
111 EmitInstructionPrologue(instr);
112 pending_deoptimization_env_ = instr->env();
113 instr->EmitNativeCode(this);
114 }
107 } 115 }
108 if (instr->next() != NULL) { 116 if (instr->next() != NULL) {
109 BlockEntryInstr* successor = instr->next()->AsBlockEntry(); 117 BlockEntryInstr* successor = instr->next()->AsBlockEntry();
110 ASSERT(successor != NULL); 118 ASSERT(successor != NULL);
111 frame_register_allocator()->Spill(); 119 frame_register_allocator()->Spill();
112 // The block ended with a "goto". We can fall through if it is the 120 // The block ended with a "goto". We can fall through if it is the
113 // next block in the list. Otherwise, we need a jump. 121 // next block in the list. Otherwise, we need a jump.
114 if ((i == block_order().length() - 1) || 122 if ((i == block_order().length() - 1) ||
115 (block_order()[i + 1] != successor)) { 123 (block_order()[i + 1] != successor)) {
116 assembler()->jmp(GetBlockLabel(successor)); 124 assembler()->jmp(GetBlockLabel(successor));
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 190
183 Label* FlowGraphCompiler::AddDeoptStub(intptr_t deopt_id, 191 Label* FlowGraphCompiler::AddDeoptStub(intptr_t deopt_id,
184 intptr_t deopt_token_pos, 192 intptr_t deopt_token_pos,
185 intptr_t try_index, 193 intptr_t try_index,
186 DeoptReasonId reason, 194 DeoptReasonId reason,
187 Register reg1, 195 Register reg1,
188 Register reg2, 196 Register reg2,
189 Register reg3) { 197 Register reg3) {
190 DeoptimizationStub* stub = 198 DeoptimizationStub* stub =
191 new DeoptimizationStub(deopt_id, deopt_token_pos, try_index, reason); 199 new DeoptimizationStub(deopt_id, deopt_token_pos, try_index, reason);
192 frame_register_allocator()->SpillInDeoptStub(stub); 200 if (pending_deoptimization_env_ == NULL) {
193 if (reg1 != kNoRegister) stub->Push(reg1); 201 frame_register_allocator()->SpillInDeoptStub(stub);
194 if (reg2 != kNoRegister) stub->Push(reg2); 202 if (reg1 != kNoRegister) stub->Push(reg1);
195 if (reg3 != kNoRegister) stub->Push(reg3); 203 if (reg2 != kNoRegister) stub->Push(reg2);
204 if (reg3 != kNoRegister) stub->Push(reg3);
205 } else {
206 stub->set_deoptimization_env(pending_deoptimization_env_);
207 }
196 deopt_stubs_.Add(stub); 208 deopt_stubs_.Add(stub);
197 return stub->entry_label(); 209 return stub->entry_label();
198 } 210 }
199 211
200 212
201 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { 213 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) {
202 ASSERT(exception_handlers_list_ != NULL); 214 ASSERT(exception_handlers_list_ != NULL);
203 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( 215 const ExceptionHandlers& handlers = ExceptionHandlers::Handle(
204 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); 216 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint()));
205 code.set_exception_handlers(handlers); 217 code.set_exception_handlers(handlers);
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 return reg; 481 return reg;
470 } 482 }
471 483
472 484
473 void FrameRegisterAllocator::SpillRegister(Register reg) { 485 void FrameRegisterAllocator::SpillRegister(Register reg) {
474 while (registers_[reg] != NULL) SpillFirst(); 486 while (registers_[reg] != NULL) SpillFirst();
475 } 487 }
476 488
477 489
478 void FrameRegisterAllocator::AllocateRegisters(Instruction* instr) { 490 void FrameRegisterAllocator::AllocateRegisters(Instruction* instr) {
491 if (is_ssa_) return;
492
479 LocationSummary* locs = instr->locs(); 493 LocationSummary* locs = instr->locs();
480 494
481 bool blocked_registers[kNumberOfCpuRegisters]; 495 bool blocked_registers[kNumberOfCpuRegisters];
482 bool blocked_temp_registers[kNumberOfCpuRegisters]; 496 bool blocked_temp_registers[kNumberOfCpuRegisters];
483 497
484 bool spill = false; 498 bool spill = false;
485 499
486 // Mark all available registers free. 500 // Mark all available registers free.
487 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { 501 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
488 blocked_registers[i] = false; 502 blocked_registers[i] = false;
489 blocked_temp_registers[i] = false; 503 blocked_temp_registers[i] = false;
490 } 504 }
491 505
492 // Mark all fixed input, temp and output registers as used. 506 // Mark all fixed input, temp and output registers as used.
493 for (intptr_t i = 0; i < locs->input_count(); i++) { 507 for (intptr_t i = 0; i < locs->input_count(); i++) {
494 Location loc = locs->in(i); 508 Location loc = locs->in(i);
495 if (loc.kind() == Location::kRegister) { 509 if (loc.IsRegister()) {
496 ASSERT(!blocked_registers[loc.reg()]); 510 ASSERT(!blocked_registers[loc.reg()]);
497 blocked_registers[loc.reg()] = true; 511 blocked_registers[loc.reg()] = true;
498 if (registers_[loc.reg()] != NULL) { 512 if (registers_[loc.reg()] != NULL) {
499 intptr_t stack_index = stack_.length() - (locs->input_count() - i); 513 intptr_t stack_index = stack_.length() - (locs->input_count() - i);
500 if ((stack_index < 0) || (stack_[stack_index] != loc.reg())) { 514 if ((stack_index < 0) || (stack_[stack_index] != loc.reg())) {
501 spill = true; 515 spill = true;
502 } 516 }
503 } 517 }
504 } 518 }
505 } 519 }
506 520
507 if (spill) Spill(); 521 if (spill) Spill();
508 522
509 for (intptr_t i = 0; i < locs->temp_count(); i++) { 523 for (intptr_t i = 0; i < locs->temp_count(); i++) {
510 Location loc = locs->temp(i); 524 Location loc = locs->temp(i);
511 if (loc.kind() == Location::kRegister) { 525 if (loc.IsRegister()) {
512 ASSERT(!blocked_registers[loc.reg()]); 526 ASSERT(!blocked_registers[loc.reg()]);
513 blocked_registers[loc.reg()] = true; 527 blocked_registers[loc.reg()] = true;
514 blocked_temp_registers[loc.reg()] = true; 528 blocked_temp_registers[loc.reg()] = true;
515 } 529 }
516 } 530 }
517 531
518 if (locs->out().kind() == Location::kRegister) { 532 if (locs->out().IsRegister()) {
519 // Fixed output registers are allowed to overlap with 533 // Fixed output registers are allowed to overlap with
520 // temps and inputs. 534 // temps and inputs.
521 blocked_registers[locs->out().reg()] = true; 535 blocked_registers[locs->out().reg()] = true;
522 } 536 }
523 537
524 // Do not allocate known registers. 538 // Do not allocate known registers.
525 blocked_registers[CTX] = true; 539 blocked_registers[CTX] = true;
526 blocked_registers[SPREG] = true; 540 blocked_registers[SPREG] = true;
527 blocked_registers[FPREG] = true; 541 blocked_registers[FPREG] = true;
528 if (TMP != kNoRegister) { 542 if (TMP != kNoRegister) {
529 blocked_registers[TMP] = true; 543 blocked_registers[TMP] = true;
530 } 544 }
531 545
532 // Allocate all unallocated input locations. 546 // Allocate all unallocated input locations.
533 for (intptr_t i = locs->input_count() - 1; i >= 0; i--) { 547 for (intptr_t i = locs->input_count() - 1; i >= 0; i--) {
534 Location loc = locs->in(i); 548 Location loc = locs->in(i);
535 Register reg = kNoRegister; 549 Register reg = kNoRegister;
536 if (loc.kind() == Location::kRegister) { 550 if (loc.IsRegister()) {
537 reg = loc.reg(); 551 reg = loc.reg();
538 } else if (loc.kind() == Location::kUnallocated) { 552 } else if (loc.IsUnallocated()) {
539 ASSERT(loc.policy() == Location::kRequiresRegister); 553 ASSERT(loc.policy() == Location::kRequiresRegister);
540 if ((stack_.length() > 0) && !blocked_temp_registers[stack_.Last()]) { 554 if ((stack_.length() > 0) && !blocked_temp_registers[stack_.Last()]) {
541 reg = stack_.Last(); 555 reg = stack_.Last();
542 blocked_registers[reg] = true; 556 blocked_registers[reg] = true;
543 } else { 557 } else {
544 reg = AllocateFreeRegister(blocked_registers); 558 reg = AllocateFreeRegister(blocked_registers);
545 } 559 }
546 locs->set_in(i, Location::RegisterLocation(reg)); 560 locs->set_in(i, Location::RegisterLocation(reg));
547 } 561 }
548 562
549 Pop(reg, instr->InputAt(i)); 563 Pop(reg, instr->InputAt(i));
550 } 564 }
551 565
552 // If this instruction is call spill everything that was not consumed by 566 // If this instruction is call spill everything that was not consumed by
553 // input locations. 567 // input locations.
554 if (locs->is_call() || locs->is_branch()) { 568 if (locs->is_call() || locs->is_branch()) {
555 Spill(); 569 Spill();
556 } 570 }
557 571
558 // Allocate all unallocated temp locations. 572 // Allocate all unallocated temp locations.
559 for (intptr_t i = 0; i < locs->temp_count(); i++) { 573 for (intptr_t i = 0; i < locs->temp_count(); i++) {
560 Location loc = locs->temp(i); 574 Location loc = locs->temp(i);
561 if (loc.kind() == Location::kUnallocated) { 575 if (loc.IsUnallocated()) {
562 ASSERT(loc.policy() == Location::kRequiresRegister); 576 ASSERT(loc.policy() == Location::kRequiresRegister);
563 loc = Location::RegisterLocation( 577 loc = Location::RegisterLocation(
564 AllocateFreeRegister(blocked_registers)); 578 AllocateFreeRegister(blocked_registers));
565 locs->set_temp(i, loc); 579 locs->set_temp(i, loc);
566 } 580 }
567 SpillRegister(loc.reg()); 581 SpillRegister(loc.reg());
568 } 582 }
569 583
570 Location result_location = locs->out(); 584 Location result_location = locs->out();
571 if (result_location.kind() == Location::kUnallocated) { 585 if (result_location.IsUnallocated()) {
572 switch (result_location.policy()) { 586 switch (result_location.policy()) {
573 case Location::kRequiresRegister: 587 case Location::kRequiresRegister:
574 result_location = Location::RegisterLocation( 588 result_location = Location::RegisterLocation(
575 AllocateFreeRegister(blocked_registers)); 589 AllocateFreeRegister(blocked_registers));
576 break; 590 break;
577 case Location::kSameAsFirstInput: 591 case Location::kSameAsFirstInput:
578 result_location = locs->in(0); 592 result_location = locs->in(0);
579 break; 593 break;
580 } 594 }
581 locs->set_out(result_location); 595 locs->set_out(result_location);
582 } 596 }
583 597
584 if (result_location.kind() == Location::kRegister) { 598 if (result_location.IsRegister()) {
585 SpillRegister(result_location.reg()); 599 SpillRegister(result_location.reg());
586 } 600 }
587 } 601 }
588 602
589 603
590 void FrameRegisterAllocator::Pop(Register dst, Value* val) { 604 void FrameRegisterAllocator::Pop(Register dst, Value* val) {
605 if (is_ssa_) return;
606
591 if (stack_.length() > 0) { 607 if (stack_.length() > 0) {
592 ASSERT(keep_values_in_registers_); 608 ASSERT(keep_values_in_registers_);
593 Register src = stack_.Last(); 609 Register src = stack_.Last();
594 ASSERT(val->AsUse()->definition() == registers_[src]); 610 ASSERT(val->AsUse()->definition() == registers_[src]);
595 stack_.RemoveLast(); 611 stack_.RemoveLast();
596 registers_[src] = NULL; 612 registers_[src] = NULL;
597 compiler()->assembler()->MoveRegister(dst, src); 613 compiler()->assembler()->MoveRegister(dst, src);
598 } else { 614 } else {
599 compiler()->assembler()->PopRegister(dst); 615 compiler()->assembler()->PopRegister(dst);
600 } 616 }
601 } 617 }
602 618
603 619
604 void FrameRegisterAllocator::Push(Register reg, BindInstr* val) { 620 void FrameRegisterAllocator::Push(Register reg, BindInstr* val) {
621 if (is_ssa_) return;
622
605 ASSERT(registers_[reg] == NULL); 623 ASSERT(registers_[reg] == NULL);
606 if (keep_values_in_registers_) { 624 if (keep_values_in_registers_) {
607 registers_[reg] = val; 625 registers_[reg] = val;
608 stack_.Add(reg); 626 stack_.Add(reg);
609 } else { 627 } else {
610 compiler()->assembler()->PushRegister(reg); 628 compiler()->assembler()->PushRegister(reg);
611 } 629 }
612 } 630 }
613 631
614 632
615 void FrameRegisterAllocator::Spill() { 633 void FrameRegisterAllocator::Spill() {
634 if (is_ssa_) return;
635
616 for (int i = 0; i < stack_.length(); i++) { 636 for (int i = 0; i < stack_.length(); i++) {
617 Register r = stack_[i]; 637 Register r = stack_[i];
618 registers_[r] = NULL; 638 registers_[r] = NULL;
619 compiler()->assembler()->PushRegister(r); 639 compiler()->assembler()->PushRegister(r);
620 } 640 }
621 stack_.Clear(); 641 stack_.Clear();
622 } 642 }
623 643
624 644
625 void FrameRegisterAllocator::SpillInDeoptStub(DeoptimizationStub* stub) { 645 void FrameRegisterAllocator::SpillInDeoptStub(DeoptimizationStub* stub) {
646 if (is_ssa_) return;
647
626 for (int i = 0; i < stack_.length(); i++) { 648 for (int i = 0; i < stack_.length(); i++) {
627 stub->Push(stack_[i]); 649 stub->Push(stack_[i]);
628 } 650 }
629 } 651 }
630 652
631 653
632 } // namespace dart 654 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698