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

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: Missed comments. 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
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 return_seen_in_block_(false), 18 return_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 518 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 } 614 }
594 615
595 616
596 void BytecodeArrayBuilder::EnsureReturn() { 617 void BytecodeArrayBuilder::EnsureReturn() {
597 if (!return_seen_in_block_) { 618 if (!return_seen_in_block_) {
598 LoadUndefined(); 619 LoadUndefined();
599 Return(); 620 Return();
600 } 621 }
601 } 622 }
602 623
624
603 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, 625 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
604 Register receiver, 626 Register receiver,
605 size_t arg_count) { 627 size_t arg_count) {
606 if (FitsInIdx8Operand(arg_count)) { 628 if (FitsInIdx8Operand(arg_count)) {
607 Output(Bytecode::kCall, callable.ToOperand(), receiver.ToOperand(), 629 Output(Bytecode::kCall, callable.ToOperand(), receiver.ToOperand(),
608 static_cast<uint8_t>(arg_count)); 630 static_cast<uint8_t>(arg_count));
609 } else { 631 } else {
610 UNIMPLEMENTED(); 632 UNIMPLEMENTED();
611 } 633 }
612 return *this; 634 return *this;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
647 entry = constants_map_.Get(object); 669 entry = constants_map_.Get(object);
648 *entry = constants_.size(); 670 *entry = constants_.size();
649 constants_.push_back(object); 671 constants_.push_back(object);
650 } 672 }
651 DCHECK(constants_[*entry].is_identical_to(object)); 673 DCHECK(constants_[*entry].is_identical_to(object));
652 return *entry; 674 return *entry;
653 } 675 }
654 676
655 677
656 int BytecodeArrayBuilder::BorrowTemporaryRegister() { 678 int BytecodeArrayBuilder::BorrowTemporaryRegister() {
657 int temporary_reg_index = temporary_register_next_++; 679 if (free_temporaries_.empty()) {
658 int count = temporary_register_next_ - fixed_register_count(); 680 temporary_register_count_ += 1;
659 if (count > temporary_register_count_) { 681 return last_temporary_register().index();
660 temporary_register_count_ = count; 682 } else {
683 auto pos = free_temporaries_.begin();
684 int retval = *pos;
685 free_temporaries_.erase(pos);
686 return retval;
661 } 687 }
662 return temporary_reg_index; 688 }
689
690
691 void BytecodeArrayBuilder::BorrowConsecutiveTemporaryRegister(int reg_index) {
692 free_temporaries_.erase(reg_index);
rmcilroy 2015/10/20 16:39:20 Could you DCHECK that the value is in free_tempora
oth 2015/10/20 20:58:42 Done.
663 } 693 }
664 694
665 695
666 void BytecodeArrayBuilder::ReturnTemporaryRegister(int reg_index) { 696 void BytecodeArrayBuilder::ReturnTemporaryRegister(int reg_index) {
667 DCHECK_EQ(reg_index, temporary_register_next_ - 1); 697 DCHECK(free_temporaries_.find(reg_index) == free_temporaries_.end());
668 temporary_register_next_ = reg_index; 698 free_temporaries_.insert(reg_index);
669 } 699 }
670 700
671 701
702 int BytecodeArrayBuilder::PrepareForConsecutiveTemporaryRegisters(
703 size_t count) {
704 if (count == 0) {
705 return -1;
706 }
707
708 // Search within existing temporaries for a run.
709 auto start = free_temporaries_.begin();
710 int run_length = 0;
711 for (auto run_end = start; run_end != free_temporaries_.end(); run_end++) {
712 if (*run_end != *start + run_length) {
713 start = run_end;
714 run_length = 0;
715 }
716 if (++run_length == count) {
717 return *start;
718 }
719 }
720
721 // Continue run if possible across existing last temporary.
722 if (temporary_register_count_ > 0 &&
723 (start == free_temporaries_.end() ||
724 *start + run_length != last_temporary_register().index() + 1)) {
725 run_length = 0;
726 }
727
728 // Ensure enough registers for run.
729 while (run_length++ < count) {
730 temporary_register_count_++;
731 free_temporaries_.insert(last_temporary_register().index());
732 }
733 return last_temporary_register().index() - static_cast<int>(count) + 1;
734 }
735
736
737 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const {
738 if (temporary_register_count_ > 0) {
739 DCHECK(reg.index() >= first_temporary_register().index() &&
740 reg.index() <= last_temporary_register().index());
741 return free_temporaries_.find(reg.index()) == free_temporaries_.end();
742 } else {
743 return false;
744 }
745 }
746
747
672 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index, 748 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index,
673 uint32_t operand_value) const { 749 uint32_t operand_value) const {
674 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index); 750 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index);
675 switch (operand_type) { 751 switch (operand_type) {
676 case OperandType::kNone: 752 case OperandType::kNone:
677 return false; 753 return false;
678 case OperandType::kIdx16: 754 case OperandType::kIdx16:
679 return static_cast<uint16_t>(operand_value) == operand_value; 755 return static_cast<uint16_t>(operand_value) == operand_value;
680 case OperandType::kCount8: 756 case OperandType::kCount8:
681 case OperandType::kImm8: 757 case OperandType::kImm8:
682 case OperandType::kIdx8: 758 case OperandType::kIdx8:
683 return static_cast<uint8_t>(operand_value) == operand_value; 759 return static_cast<uint8_t>(operand_value) == operand_value;
684 case OperandType::kReg8: { 760 case OperandType::kReg8: {
685 Register reg = Register::FromOperand(static_cast<uint8_t>(operand_value)); 761 Register reg = Register::FromOperand(static_cast<uint8_t>(operand_value));
686 if (reg.is_function_context() || reg.is_function_closure()) { 762 if (reg.is_function_context() || reg.is_function_closure()) {
687 return true; 763 return true;
688 } else if (reg.is_parameter()) { 764 } else if (reg.is_parameter()) {
689 int parameter_index = reg.ToParameterIndex(parameter_count()); 765 int parameter_index = reg.ToParameterIndex(parameter_count_);
690 return parameter_index >= 0 && parameter_index < parameter_count(); 766 return parameter_index >= 0 && parameter_index < parameter_count_;
767 } else if (reg.index() < fixed_register_count()) {
768 return true;
691 } else { 769 } else {
692 return (reg.index() >= 0 && reg.index() < temporary_register_next_); 770 return TemporaryRegisterIsLive(reg);
693 } 771 }
694 } 772 }
695 } 773 }
696 UNREACHABLE(); 774 UNREACHABLE();
697 return false; 775 return false;
698 } 776 }
699 777
700 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { 778 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const {
701 return last_bytecode_start_ < bytecodes()->size() && 779 return last_bytecode_start_ < bytecodes()->size() &&
702 last_bytecode_start_ >= last_block_end_; 780 last_bytecode_start_ >= last_block_end_;
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
866 } 944 }
867 945
868 946
869 // static 947 // static
870 bool BytecodeArrayBuilder::FitsInIdx16Operand(int value) { 948 bool BytecodeArrayBuilder::FitsInIdx16Operand(int value) {
871 return kMinUInt16 <= value && value <= kMaxUInt16; 949 return kMinUInt16 <= value && value <= kMaxUInt16;
872 } 950 }
873 951
874 952
875 TemporaryRegisterScope::TemporaryRegisterScope(BytecodeArrayBuilder* builder) 953 TemporaryRegisterScope::TemporaryRegisterScope(BytecodeArrayBuilder* builder)
876 : builder_(builder), count_(0), last_register_index_(-1) {} 954 : builder_(builder),
955 allocated_(builder->zone()),
956 next_consecutive_register_(-1),
957 next_consecutive_count_(-1) {
958 // TODO(oth): Deprecate TemporaryRegisterScope use. Should be using
959 // result scopes as far as possible.
rmcilroy 2015/10/20 16:39:20 nit - move TODO to TemporaryRegisterScope declarat
oth 2015/10/20 20:58:42 Done.
960 }
877 961
878 962
879 TemporaryRegisterScope::~TemporaryRegisterScope() { 963 TemporaryRegisterScope::~TemporaryRegisterScope() {
880 while (count_-- != 0) { 964 for (auto i = allocated_.rbegin(); i != allocated_.rend(); i++) {
881 builder_->ReturnTemporaryRegister(last_register_index_--); 965 builder_->ReturnTemporaryRegister(*i);
966 }
967 allocated_.clear();
968 }
969
970
971 Register TemporaryRegisterScope::NewRegister() {
972 int allocated = builder_->BorrowTemporaryRegister();
973 allocated_.push_back(allocated);
974 return Register(allocated);
975 }
976
977
978 void TemporaryRegisterScope::PrepareForConsecutiveAllocations(size_t count) {
979 if (static_cast<int>(count) > next_consecutive_count_) {
980 next_consecutive_register_ =
981 builder_->PrepareForConsecutiveTemporaryRegisters(count);
982 next_consecutive_count_ = static_cast<int>(count);
882 } 983 }
883 } 984 }
884 985
885 986
886 Register TemporaryRegisterScope::NewRegister() { 987 Register TemporaryRegisterScope::NextConsecutiveRegister() {
887 count_++; 988 DCHECK_GE(next_consecutive_register_, 0);
888 last_register_index_ = builder_->BorrowTemporaryRegister(); 989 DCHECK_GT(next_consecutive_count_, 0);
889 return Register(last_register_index_); 990 builder_->BorrowConsecutiveTemporaryRegister(next_consecutive_register_);
991 allocated_.push_back(next_consecutive_register_);
992 next_consecutive_count_--;
993 return Register(next_consecutive_register_++);
890 } 994 }
891 995
892 } // namespace interpreter 996 } // namespace interpreter
893 } // namespace internal 997 } // namespace internal
894 } // namespace v8 998 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698