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

Side by Side Diff: src/interpreter/bytecode-array-builder.cc

Issue 1392933002: [Interpreter] Reduce temporary register usage in generated bytecode. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Incorporate comments from mstarzinger. Created 5 years, 2 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
« no previous file with comments | « src/interpreter/bytecode-array-builder.h ('k') | src/interpreter/bytecode-generator.h » ('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 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 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-array-builder.h" 5 #include "src/interpreter/bytecode-array-builder.h"
6 6
7 namespace v8 { 7 namespace v8 {
8 namespace internal { 8 namespace internal {
9 namespace interpreter { 9 namespace interpreter {
10 10
11 BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone) 11 BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone)
12 : isolate_(isolate), 12 : isolate_(isolate),
13 zone_(zone), 13 zone_(zone),
14 bytecodes_(zone), 14 bytecodes_(zone),
15 bytecode_generated_(false), 15 bytecode_generated_(false),
16 last_block_end_(0), 16 last_block_end_(0),
17 last_bytecode_start_(~0), 17 last_bytecode_start_(~0),
18 exit_seen_in_block_(false), 18 exit_seen_in_block_(false),
19 constants_map_(isolate->heap(), zone), 19 constants_map_(isolate->heap(), zone),
20 constants_(zone), 20 constants_(zone),
21 parameter_count_(-1), 21 parameter_count_(-1),
22 local_register_count_(-1), 22 local_register_count_(-1),
23 context_register_count_(-1), 23 context_register_count_(-1),
24 temporary_register_count_(0), 24 temporary_register_count_(0),
25 temporary_register_next_(0) {} 25 free_temporaries_(zone) {}
26 26
27 27
28 void BytecodeArrayBuilder::set_locals_count(int number_of_locals) { 28 void BytecodeArrayBuilder::set_locals_count(int number_of_locals) {
29 local_register_count_ = number_of_locals; 29 local_register_count_ = number_of_locals;
30 DCHECK_LE(context_register_count_, 0); 30 DCHECK_LE(context_register_count_, 0);
31 temporary_register_next_ = local_register_count_;
32 } 31 }
33 32
34 33
35 void BytecodeArrayBuilder::set_parameter_count(int number_of_parameters) { 34 void BytecodeArrayBuilder::set_parameter_count(int number_of_parameters) {
36 parameter_count_ = number_of_parameters; 35 parameter_count_ = number_of_parameters;
37 } 36 }
38 37
39 38
40 void BytecodeArrayBuilder::set_context_count(int number_of_contexts) { 39 void BytecodeArrayBuilder::set_context_count(int number_of_contexts) {
41 context_register_count_ = number_of_contexts; 40 context_register_count_ = number_of_contexts;
42 DCHECK_GE(local_register_count_, 0); 41 DCHECK_GE(local_register_count_, 0);
43 temporary_register_next_ = local_register_count_ + context_register_count_;
44 } 42 }
45 43
46 44
47 Register BytecodeArrayBuilder::first_context_register() const { 45 Register BytecodeArrayBuilder::first_context_register() const {
48 DCHECK_GT(context_register_count_, 0); 46 DCHECK_GT(context_register_count_, 0);
49 return Register(local_register_count_); 47 return Register(local_register_count_);
50 } 48 }
51 49
52 50
53 Register BytecodeArrayBuilder::last_context_register() const { 51 Register BytecodeArrayBuilder::last_context_register() const {
54 DCHECK_GT(context_register_count_, 0); 52 DCHECK_GT(context_register_count_, 0);
55 return Register(local_register_count_ + context_register_count_ - 1); 53 return Register(local_register_count_ + context_register_count_ - 1);
56 } 54 }
57 55
58 56
57 Register BytecodeArrayBuilder::first_temporary_register() const {
58 DCHECK_GT(temporary_register_count_, 0);
59 return Register(fixed_register_count());
60 }
61
62
63 Register BytecodeArrayBuilder::last_temporary_register() const {
64 DCHECK_GT(temporary_register_count_, 0);
65 return Register(fixed_register_count() + temporary_register_count_ - 1);
66 }
67
68
59 Register BytecodeArrayBuilder::Parameter(int parameter_index) const { 69 Register BytecodeArrayBuilder::Parameter(int parameter_index) const {
60 DCHECK_GE(parameter_index, 0); 70 DCHECK_GE(parameter_index, 0);
61 return Register::FromParameterIndex(parameter_index, parameter_count()); 71 return Register::FromParameterIndex(parameter_index, parameter_count());
62 } 72 }
63 73
64 74
75 bool BytecodeArrayBuilder::RegisterIsParameterOrLocal(Register reg) const {
76 return reg.is_parameter() || reg.index() < locals_count();
77 }
78
79
80 bool BytecodeArrayBuilder::RegisterIsTemporary(Register reg) const {
81 return temporary_register_count_ > 0 && first_temporary_register() <= reg &&
82 reg <= last_temporary_register();
83 }
84
85
65 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { 86 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() {
66 DCHECK_EQ(bytecode_generated_, false); 87 DCHECK_EQ(bytecode_generated_, false);
67 88
68 EnsureReturn(); 89 EnsureReturn();
69 90
70 int bytecode_size = static_cast<int>(bytecodes_.size()); 91 int bytecode_size = static_cast<int>(bytecodes_.size());
71 int register_count = fixed_register_count() + temporary_register_count_; 92 int register_count = fixed_register_count() + temporary_register_count_;
72 int frame_size = register_count * kPointerSize; 93 int frame_size = register_count * kPointerSize;
73 94
74 Factory* factory = isolate_->factory(); 95 Factory* factory = isolate_->factory();
(...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 } 621 }
601 622
602 623
603 void BytecodeArrayBuilder::EnsureReturn() { 624 void BytecodeArrayBuilder::EnsureReturn() {
604 if (!exit_seen_in_block_) { 625 if (!exit_seen_in_block_) {
605 LoadUndefined(); 626 LoadUndefined();
606 Return(); 627 Return();
607 } 628 }
608 } 629 }
609 630
631
610 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, 632 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
611 Register receiver, 633 Register receiver,
612 size_t arg_count) { 634 size_t arg_count) {
613 if (FitsInIdx8Operand(arg_count)) { 635 if (FitsInIdx8Operand(arg_count)) {
614 Output(Bytecode::kCall, callable.ToOperand(), receiver.ToOperand(), 636 Output(Bytecode::kCall, callable.ToOperand(), receiver.ToOperand(),
615 static_cast<uint8_t>(arg_count)); 637 static_cast<uint8_t>(arg_count));
616 } else { 638 } else {
617 UNIMPLEMENTED(); 639 UNIMPLEMENTED();
618 } 640 }
619 return *this; 641 return *this;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 entry = constants_map_.Get(object); 676 entry = constants_map_.Get(object);
655 *entry = constants_.size(); 677 *entry = constants_.size();
656 constants_.push_back(object); 678 constants_.push_back(object);
657 } 679 }
658 DCHECK(constants_[*entry].is_identical_to(object)); 680 DCHECK(constants_[*entry].is_identical_to(object));
659 return *entry; 681 return *entry;
660 } 682 }
661 683
662 684
663 int BytecodeArrayBuilder::BorrowTemporaryRegister() { 685 int BytecodeArrayBuilder::BorrowTemporaryRegister() {
664 int temporary_reg_index = temporary_register_next_++; 686 if (free_temporaries_.empty()) {
665 int count = temporary_register_next_ - fixed_register_count(); 687 temporary_register_count_ += 1;
666 if (count > temporary_register_count_) { 688 return last_temporary_register().index();
667 temporary_register_count_ = count; 689 } else {
690 auto pos = free_temporaries_.begin();
691 int retval = *pos;
692 free_temporaries_.erase(pos);
693 return retval;
668 } 694 }
669 return temporary_reg_index; 695 }
696
697
698 void BytecodeArrayBuilder::BorrowConsecutiveTemporaryRegister(int reg_index) {
699 DCHECK(free_temporaries_.find(reg_index) != free_temporaries_.end());
700 free_temporaries_.erase(reg_index);
670 } 701 }
671 702
672 703
673 void BytecodeArrayBuilder::ReturnTemporaryRegister(int reg_index) { 704 void BytecodeArrayBuilder::ReturnTemporaryRegister(int reg_index) {
674 DCHECK_EQ(reg_index, temporary_register_next_ - 1); 705 DCHECK(free_temporaries_.find(reg_index) == free_temporaries_.end());
675 temporary_register_next_ = reg_index; 706 free_temporaries_.insert(reg_index);
676 } 707 }
677 708
678 709
710 int BytecodeArrayBuilder::PrepareForConsecutiveTemporaryRegisters(
711 size_t count) {
712 if (count == 0) {
713 return -1;
714 }
715
716 // Search within existing temporaries for a run.
717 auto start = free_temporaries_.begin();
718 size_t run_length = 0;
719 for (auto run_end = start; run_end != free_temporaries_.end(); run_end++) {
720 if (*run_end != *start + static_cast<int>(run_length)) {
721 start = run_end;
722 run_length = 0;
723 }
724 if (++run_length == count) {
725 return *start;
726 }
727 }
728
729 // Continue run if possible across existing last temporary.
730 if (temporary_register_count_ > 0 &&
731 (start == free_temporaries_.end() ||
732 *start + static_cast<int>(run_length) !=
733 last_temporary_register().index() + 1)) {
734 run_length = 0;
735 }
736
737 // Ensure enough registers for run.
738 while (run_length++ < count) {
739 temporary_register_count_++;
740 free_temporaries_.insert(last_temporary_register().index());
741 }
742 return last_temporary_register().index() - static_cast<int>(count) + 1;
743 }
744
745
746 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const {
747 if (temporary_register_count_ > 0) {
748 DCHECK(reg.index() >= first_temporary_register().index() &&
749 reg.index() <= last_temporary_register().index());
750 return free_temporaries_.find(reg.index()) == free_temporaries_.end();
751 } else {
752 return false;
753 }
754 }
755
756
679 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index, 757 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index,
680 uint32_t operand_value) const { 758 uint32_t operand_value) const {
681 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index); 759 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index);
682 switch (operand_type) { 760 switch (operand_type) {
683 case OperandType::kNone: 761 case OperandType::kNone:
684 return false; 762 return false;
685 case OperandType::kIdx16: 763 case OperandType::kIdx16:
686 return static_cast<uint16_t>(operand_value) == operand_value; 764 return static_cast<uint16_t>(operand_value) == operand_value;
687 case OperandType::kCount8: 765 case OperandType::kCount8:
688 case OperandType::kImm8: 766 case OperandType::kImm8:
689 case OperandType::kIdx8: 767 case OperandType::kIdx8:
690 return static_cast<uint8_t>(operand_value) == operand_value; 768 return static_cast<uint8_t>(operand_value) == operand_value;
691 case OperandType::kReg8: { 769 case OperandType::kReg8: {
692 Register reg = Register::FromOperand(static_cast<uint8_t>(operand_value)); 770 Register reg = Register::FromOperand(static_cast<uint8_t>(operand_value));
693 if (reg.is_function_context() || reg.is_function_closure()) { 771 if (reg.is_function_context() || reg.is_function_closure()) {
694 return true; 772 return true;
695 } else if (reg.is_parameter()) { 773 } else if (reg.is_parameter()) {
696 int parameter_index = reg.ToParameterIndex(parameter_count()); 774 int parameter_index = reg.ToParameterIndex(parameter_count_);
697 return parameter_index >= 0 && parameter_index < parameter_count(); 775 return parameter_index >= 0 && parameter_index < parameter_count_;
776 } else if (reg.index() < fixed_register_count()) {
777 return true;
698 } else { 778 } else {
699 return (reg.index() >= 0 && reg.index() < temporary_register_next_); 779 return TemporaryRegisterIsLive(reg);
700 } 780 }
701 } 781 }
702 } 782 }
703 UNREACHABLE(); 783 UNREACHABLE();
704 return false; 784 return false;
705 } 785 }
706 786
707 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { 787 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const {
708 return last_bytecode_start_ < bytecodes()->size() && 788 return last_bytecode_start_ < bytecodes()->size() &&
709 last_bytecode_start_ >= last_block_end_; 789 last_bytecode_start_ >= last_block_end_;
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 } 953 }
874 954
875 955
876 // static 956 // static
877 bool BytecodeArrayBuilder::FitsInIdx16Operand(int value) { 957 bool BytecodeArrayBuilder::FitsInIdx16Operand(int value) {
878 return kMinUInt16 <= value && value <= kMaxUInt16; 958 return kMinUInt16 <= value && value <= kMaxUInt16;
879 } 959 }
880 960
881 961
882 TemporaryRegisterScope::TemporaryRegisterScope(BytecodeArrayBuilder* builder) 962 TemporaryRegisterScope::TemporaryRegisterScope(BytecodeArrayBuilder* builder)
883 : builder_(builder), count_(0), last_register_index_(-1) {} 963 : builder_(builder),
964 allocated_(builder->zone()),
965 next_consecutive_register_(-1),
966 next_consecutive_count_(-1) {}
884 967
885 968
886 TemporaryRegisterScope::~TemporaryRegisterScope() { 969 TemporaryRegisterScope::~TemporaryRegisterScope() {
887 while (count_-- != 0) { 970 for (auto i = allocated_.rbegin(); i != allocated_.rend(); i++) {
888 builder_->ReturnTemporaryRegister(last_register_index_--); 971 builder_->ReturnTemporaryRegister(*i);
972 }
973 allocated_.clear();
974 }
975
976
977 Register TemporaryRegisterScope::NewRegister() {
978 int allocated = builder_->BorrowTemporaryRegister();
979 allocated_.push_back(allocated);
980 return Register(allocated);
981 }
982
983
984 void TemporaryRegisterScope::PrepareForConsecutiveAllocations(size_t count) {
985 if (static_cast<int>(count) > next_consecutive_count_) {
986 next_consecutive_register_ =
987 builder_->PrepareForConsecutiveTemporaryRegisters(count);
988 next_consecutive_count_ = static_cast<int>(count);
889 } 989 }
890 } 990 }
891 991
892 992
893 Register TemporaryRegisterScope::NewRegister() { 993 Register TemporaryRegisterScope::NextConsecutiveRegister() {
894 count_++; 994 DCHECK_GE(next_consecutive_register_, 0);
895 last_register_index_ = builder_->BorrowTemporaryRegister(); 995 DCHECK_GT(next_consecutive_count_, 0);
896 return Register(last_register_index_); 996 builder_->BorrowConsecutiveTemporaryRegister(next_consecutive_register_);
997 allocated_.push_back(next_consecutive_register_);
998 next_consecutive_count_--;
999 return Register(next_consecutive_register_++);
897 } 1000 }
898 1001
899 } // namespace interpreter 1002 } // namespace interpreter
900 } // namespace internal 1003 } // namespace internal
901 } // namespace v8 1004 } // namespace v8
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-array-builder.h ('k') | src/interpreter/bytecode-generator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698