OLD | NEW |
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 #include "src/compiler.h" | 7 #include "src/compiler.h" |
8 #include "src/interpreter/bytecode-array-writer.h" | 8 #include "src/interpreter/bytecode-array-writer.h" |
9 #include "src/interpreter/bytecode-peephole-optimizer.h" | 9 #include "src/interpreter/bytecode-peephole-optimizer.h" |
10 #include "src/interpreter/bytecode-register-optimizer.h" | 10 #include "src/interpreter/bytecode-register-optimizer.h" |
11 #include "src/interpreter/interpreter-intrinsics.h" | 11 #include "src/interpreter/interpreter-intrinsics.h" |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 namespace interpreter { | 15 namespace interpreter { |
16 | 16 |
17 BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone, | 17 BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone, |
18 int parameter_count, | 18 int parameter_count, |
19 int context_count, int locals_count, | 19 int context_count, int locals_count, |
20 FunctionLiteral* literal) | 20 FunctionLiteral* literal) |
21 : isolate_(isolate), | 21 : isolate_(isolate), |
22 zone_(zone), | 22 zone_(zone), |
23 bytecode_generated_(false), | 23 bytecode_generated_(false), |
24 constant_array_builder_(isolate, zone), | 24 constant_array_builder_(isolate, zone), |
25 handler_table_builder_(isolate, zone), | 25 handler_table_builder_(isolate, zone), |
26 source_position_table_builder_(isolate, zone), | 26 source_position_table_builder_(isolate, zone), |
27 exit_seen_in_block_(false), | 27 return_seen_in_block_(false), |
28 unbound_jumps_(0), | 28 unbound_jumps_(0), |
29 parameter_count_(parameter_count), | 29 parameter_count_(parameter_count), |
30 local_register_count_(locals_count), | 30 local_register_count_(locals_count), |
31 context_register_count_(context_count), | 31 context_register_count_(context_count), |
32 temporary_allocator_(zone, fixed_register_count()), | 32 temporary_allocator_(zone, fixed_register_count()), |
33 bytecode_array_writer_(zone, &source_position_table_builder_), | 33 bytecode_array_writer_(zone, &source_position_table_builder_), |
34 pipeline_(&bytecode_array_writer_) { | 34 pipeline_(&bytecode_array_writer_) { |
35 DCHECK_GE(parameter_count_, 0); | 35 DCHECK_GE(parameter_count_, 0); |
36 DCHECK_GE(context_register_count_, 0); | 36 DCHECK_GE(context_register_count_, 0); |
37 DCHECK_GE(local_register_count_, 0); | 37 DCHECK_GE(local_register_count_, 0); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 | 72 |
73 | 73 |
74 bool BytecodeArrayBuilder::RegisterIsParameterOrLocal(Register reg) const { | 74 bool BytecodeArrayBuilder::RegisterIsParameterOrLocal(Register reg) const { |
75 return reg.is_parameter() || reg.index() < locals_count(); | 75 return reg.is_parameter() || reg.index() < locals_count(); |
76 } | 76 } |
77 | 77 |
78 | 78 |
79 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { | 79 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { |
80 DCHECK_EQ(0, unbound_jumps_); | 80 DCHECK_EQ(0, unbound_jumps_); |
81 DCHECK_EQ(bytecode_generated_, false); | 81 DCHECK_EQ(bytecode_generated_, false); |
82 DCHECK(exit_seen_in_block_); | 82 DCHECK(return_seen_in_block_); |
83 | 83 |
84 pipeline()->FlushBasicBlock(); | 84 pipeline()->FlushBasicBlock(); |
85 const ZoneVector<uint8_t>* bytecodes = bytecode_array_writer()->bytecodes(); | 85 const ZoneVector<uint8_t>* bytecodes = bytecode_array_writer()->bytecodes(); |
86 | 86 |
87 int bytecode_size = static_cast<int>(bytecodes->size()); | 87 int bytecode_size = static_cast<int>(bytecodes->size()); |
88 | 88 |
89 // All locals need a frame slot for the debugger, but may not be | 89 // All locals need a frame slot for the debugger, but may not be |
90 // present in generated code. | 90 // present in generated code. |
91 int frame_size_for_locals = fixed_register_count() * kPointerSize; | 91 int frame_size_for_locals = fixed_register_count() * kPointerSize; |
92 int frame_size_used = bytecode_array_writer()->GetMaximumFrameSizeUsed(); | 92 int frame_size_used = bytecode_array_writer()->GetMaximumFrameSizeUsed(); |
(...skipping 17 matching lines...) Expand all Loading... |
110 } | 110 } |
111 | 111 |
112 void BytecodeArrayBuilder::AttachSourceInfo(BytecodeNode* node) { | 112 void BytecodeArrayBuilder::AttachSourceInfo(BytecodeNode* node) { |
113 if (latest_source_info_.is_valid()) { | 113 if (latest_source_info_.is_valid()) { |
114 node->source_info().Update(latest_source_info_); | 114 node->source_info().Update(latest_source_info_); |
115 latest_source_info_.set_invalid(); | 115 latest_source_info_.set_invalid(); |
116 } | 116 } |
117 } | 117 } |
118 | 118 |
119 void BytecodeArrayBuilder::Output(Bytecode bytecode) { | 119 void BytecodeArrayBuilder::Output(Bytecode bytecode) { |
120 // Don't output dead code. | |
121 if (exit_seen_in_block_) return; | |
122 | |
123 BytecodeNode node(bytecode); | 120 BytecodeNode node(bytecode); |
124 AttachSourceInfo(&node); | 121 AttachSourceInfo(&node); |
125 pipeline()->Write(&node); | 122 pipeline()->Write(&node); |
126 } | 123 } |
127 | 124 |
128 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, | 125 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, |
129 OperandScale operand_scale, | 126 OperandScale operand_scale, |
130 uint32_t operand0, uint32_t operand1, | 127 uint32_t operand0, uint32_t operand1, |
131 uint32_t operand2, uint32_t operand3) { | 128 uint32_t operand2, uint32_t operand3) { |
132 // Don't output dead code. | |
133 if (exit_seen_in_block_) return; | |
134 DCHECK(OperandIsValid(bytecode, operand_scale, 0, operand0)); | 129 DCHECK(OperandIsValid(bytecode, operand_scale, 0, operand0)); |
135 DCHECK(OperandIsValid(bytecode, operand_scale, 1, operand1)); | 130 DCHECK(OperandIsValid(bytecode, operand_scale, 1, operand1)); |
136 DCHECK(OperandIsValid(bytecode, operand_scale, 2, operand2)); | 131 DCHECK(OperandIsValid(bytecode, operand_scale, 2, operand2)); |
137 DCHECK(OperandIsValid(bytecode, operand_scale, 3, operand3)); | 132 DCHECK(OperandIsValid(bytecode, operand_scale, 3, operand3)); |
138 BytecodeNode node(bytecode, operand0, operand1, operand2, operand3, | 133 BytecodeNode node(bytecode, operand0, operand1, operand2, operand3, |
139 operand_scale); | 134 operand_scale); |
140 AttachSourceInfo(&node); | 135 AttachSourceInfo(&node); |
141 pipeline()->Write(&node); | 136 pipeline()->Write(&node); |
142 } | 137 } |
143 | 138 |
144 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, | 139 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, |
145 OperandScale operand_scale, | 140 OperandScale operand_scale, |
146 uint32_t operand0, uint32_t operand1, | 141 uint32_t operand0, uint32_t operand1, |
147 uint32_t operand2) { | 142 uint32_t operand2) { |
148 // Don't output dead code. | |
149 if (exit_seen_in_block_) return; | |
150 DCHECK(OperandIsValid(bytecode, operand_scale, 0, operand0)); | 143 DCHECK(OperandIsValid(bytecode, operand_scale, 0, operand0)); |
151 DCHECK(OperandIsValid(bytecode, operand_scale, 1, operand1)); | 144 DCHECK(OperandIsValid(bytecode, operand_scale, 1, operand1)); |
152 DCHECK(OperandIsValid(bytecode, operand_scale, 2, operand2)); | 145 DCHECK(OperandIsValid(bytecode, operand_scale, 2, operand2)); |
153 BytecodeNode node(bytecode, operand0, operand1, operand2, operand_scale); | 146 BytecodeNode node(bytecode, operand0, operand1, operand2, operand_scale); |
154 AttachSourceInfo(&node); | 147 AttachSourceInfo(&node); |
155 pipeline()->Write(&node); | 148 pipeline()->Write(&node); |
156 } | 149 } |
157 | 150 |
158 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, | 151 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, |
159 OperandScale operand_scale, | 152 OperandScale operand_scale, |
160 uint32_t operand0, uint32_t operand1) { | 153 uint32_t operand0, uint32_t operand1) { |
161 // Don't output dead code. | |
162 if (exit_seen_in_block_) return; | |
163 DCHECK(OperandIsValid(bytecode, operand_scale, 0, operand0)); | 154 DCHECK(OperandIsValid(bytecode, operand_scale, 0, operand0)); |
164 DCHECK(OperandIsValid(bytecode, operand_scale, 1, operand1)); | 155 DCHECK(OperandIsValid(bytecode, operand_scale, 1, operand1)); |
165 BytecodeNode node(bytecode, operand0, operand1, operand_scale); | 156 BytecodeNode node(bytecode, operand0, operand1, operand_scale); |
166 AttachSourceInfo(&node); | 157 AttachSourceInfo(&node); |
167 pipeline()->Write(&node); | 158 pipeline()->Write(&node); |
168 } | 159 } |
169 | 160 |
170 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, | 161 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, |
171 OperandScale operand_scale, | 162 OperandScale operand_scale, |
172 uint32_t operand0) { | 163 uint32_t operand0) { |
173 // Don't output dead code. | |
174 if (exit_seen_in_block_) return; | |
175 DCHECK(OperandIsValid(bytecode, operand_scale, 0, operand0)); | 164 DCHECK(OperandIsValid(bytecode, operand_scale, 0, operand0)); |
176 BytecodeNode node(bytecode, operand0, operand_scale); | 165 BytecodeNode node(bytecode, operand0, operand_scale); |
177 AttachSourceInfo(&node); | 166 AttachSourceInfo(&node); |
178 pipeline()->Write(&node); | 167 pipeline()->Write(&node); |
179 } | 168 } |
180 | 169 |
181 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, | 170 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, |
182 Register reg) { | 171 Register reg) { |
183 OperandScale operand_scale = | 172 OperandScale operand_scale = |
184 Bytecodes::OperandSizesToScale(reg.SizeOfOperand()); | 173 Bytecodes::OperandSizesToScale(reg.SizeOfOperand()); |
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
659 break; | 648 break; |
660 default: | 649 default: |
661 UNREACHABLE(); | 650 UNREACHABLE(); |
662 } | 651 } |
663 unbound_jumps_--; | 652 unbound_jumps_--; |
664 } | 653 } |
665 | 654 |
666 | 655 |
667 BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(Bytecode jump_bytecode, | 656 BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(Bytecode jump_bytecode, |
668 BytecodeLabel* label) { | 657 BytecodeLabel* label) { |
669 // Don't emit dead code. | |
670 if (exit_seen_in_block_) return *this; | |
671 | |
672 if (label->is_bound()) { | 658 if (label->is_bound()) { |
673 // Label has been bound already so this is a backwards jump. | 659 // Label has been bound already so this is a backwards jump. |
674 size_t current_offset = pipeline()->FlushForOffset(); | 660 size_t current_offset = pipeline()->FlushForOffset(); |
675 CHECK_GE(current_offset, label->offset()); | 661 CHECK_GE(current_offset, label->offset()); |
676 CHECK_LE(current_offset, static_cast<size_t>(kMaxInt)); | 662 CHECK_LE(current_offset, static_cast<size_t>(kMaxInt)); |
677 size_t abs_delta = current_offset - label->offset(); | 663 size_t abs_delta = current_offset - label->offset(); |
678 int delta = -static_cast<int>(abs_delta); | 664 int delta = -static_cast<int>(abs_delta); |
679 OperandSize operand_size = Bytecodes::SizeForSignedOperand(delta); | 665 OperandSize operand_size = Bytecodes::SizeForSignedOperand(delta); |
680 if (operand_size > OperandSize::kByte) { | 666 if (operand_size > OperandSize::kByte) { |
681 // Adjust for scaling byte prefix for wide jump offset. | 667 // Adjust for scaling byte prefix for wide jump offset. |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
747 return *this; | 733 return *this; |
748 } | 734 } |
749 | 735 |
750 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole( | 736 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole( |
751 BytecodeLabel* label) { | 737 BytecodeLabel* label) { |
752 return OutputJump(Bytecode::kJumpIfNotHole, label); | 738 return OutputJump(Bytecode::kJumpIfNotHole, label); |
753 } | 739 } |
754 | 740 |
755 BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() { | 741 BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() { |
756 Output(Bytecode::kThrow); | 742 Output(Bytecode::kThrow); |
757 exit_seen_in_block_ = true; | |
758 return *this; | 743 return *this; |
759 } | 744 } |
760 | 745 |
761 | 746 |
762 BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() { | 747 BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() { |
763 Output(Bytecode::kReThrow); | 748 Output(Bytecode::kReThrow); |
764 exit_seen_in_block_ = true; | |
765 return *this; | 749 return *this; |
766 } | 750 } |
767 | 751 |
768 | 752 |
769 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() { | 753 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() { |
770 Output(Bytecode::kReturn); | 754 Output(Bytecode::kReturn); |
771 exit_seen_in_block_ = true; | 755 return_seen_in_block_ = true; |
772 return *this; | 756 return *this; |
773 } | 757 } |
774 | 758 |
775 BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() { | 759 BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() { |
776 Output(Bytecode::kDebugger); | 760 Output(Bytecode::kDebugger); |
777 return *this; | 761 return *this; |
778 } | 762 } |
779 | 763 |
780 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare( | 764 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare( |
781 Register cache_info_triple) { | 765 Register cache_info_triple) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
856 | 840 |
857 | 841 |
858 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) { | 842 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) { |
859 size_t offset = pipeline()->FlushForOffset(); | 843 size_t offset = pipeline()->FlushForOffset(); |
860 handler_table_builder()->SetTryRegionEnd(handler_id, offset); | 844 handler_table_builder()->SetTryRegionEnd(handler_id, offset); |
861 return *this; | 845 return *this; |
862 } | 846 } |
863 | 847 |
864 | 848 |
865 void BytecodeArrayBuilder::LeaveBasicBlock() { | 849 void BytecodeArrayBuilder::LeaveBasicBlock() { |
866 exit_seen_in_block_ = false; | |
867 pipeline()->FlushBasicBlock(); | 850 pipeline()->FlushBasicBlock(); |
| 851 return_seen_in_block_ = false; |
868 } | 852 } |
869 | 853 |
870 void BytecodeArrayBuilder::EnsureReturn() { | 854 void BytecodeArrayBuilder::EnsureReturn() { |
871 if (!exit_seen_in_block_) { | 855 if (!return_seen_in_block_) { |
872 LoadUndefined(); | 856 LoadUndefined(); |
873 SetReturnPosition(); | 857 SetReturnPosition(); |
874 Return(); | 858 Return(); |
875 } | 859 } |
876 DCHECK(exit_seen_in_block_); | 860 DCHECK(return_seen_in_block_); |
877 } | 861 } |
878 | 862 |
879 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, | 863 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, |
880 Register receiver_args, | 864 Register receiver_args, |
881 size_t receiver_args_count, | 865 size_t receiver_args_count, |
882 int feedback_slot, | 866 int feedback_slot, |
883 TailCallMode tail_call_mode) { | 867 TailCallMode tail_call_mode) { |
884 Bytecode bytecode = BytecodeForCall(tail_call_mode); | 868 Bytecode bytecode = BytecodeForCall(tail_call_mode); |
885 OperandScale operand_scale = Bytecodes::OperandSizesToScale( | 869 OperandScale operand_scale = Bytecodes::OperandSizesToScale( |
886 callable.SizeOfOperand(), receiver_args.SizeOfOperand(), | 870 callable.SizeOfOperand(), receiver_args.SizeOfOperand(), |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
967 RegisterOperand(object)); | 951 RegisterOperand(object)); |
968 return *this; | 952 return *this; |
969 } | 953 } |
970 | 954 |
971 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { | 955 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { |
972 return constant_array_builder()->Insert(object); | 956 return constant_array_builder()->Insert(object); |
973 } | 957 } |
974 | 958 |
975 void BytecodeArrayBuilder::SetReturnPosition() { | 959 void BytecodeArrayBuilder::SetReturnPosition() { |
976 if (return_position_ == RelocInfo::kNoPosition) return; | 960 if (return_position_ == RelocInfo::kNoPosition) return; |
977 if (exit_seen_in_block_) return; | |
978 latest_source_info_.Update({return_position_, true}); | 961 latest_source_info_.Update({return_position_, true}); |
979 } | 962 } |
980 | 963 |
981 void BytecodeArrayBuilder::SetStatementPosition(Statement* stmt) { | 964 void BytecodeArrayBuilder::SetStatementPosition(Statement* stmt) { |
982 if (stmt->position() == RelocInfo::kNoPosition) return; | 965 if (stmt->position() == RelocInfo::kNoPosition) return; |
983 if (exit_seen_in_block_) return; | |
984 latest_source_info_.Update({stmt->position(), true}); | 966 latest_source_info_.Update({stmt->position(), true}); |
985 } | 967 } |
986 | 968 |
987 void BytecodeArrayBuilder::SetExpressionPosition(Expression* expr) { | 969 void BytecodeArrayBuilder::SetExpressionPosition(Expression* expr) { |
988 if (expr->position() == RelocInfo::kNoPosition) return; | 970 if (expr->position() == RelocInfo::kNoPosition) return; |
989 if (exit_seen_in_block_) return; | |
990 latest_source_info_.Update({expr->position(), false}); | 971 latest_source_info_.Update({expr->position(), false}); |
991 } | 972 } |
992 | 973 |
993 void BytecodeArrayBuilder::SetExpressionAsStatementPosition(Expression* expr) { | 974 void BytecodeArrayBuilder::SetExpressionAsStatementPosition(Expression* expr) { |
994 if (expr->position() == RelocInfo::kNoPosition) return; | 975 if (expr->position() == RelocInfo::kNoPosition) return; |
995 if (exit_seen_in_block_) return; | |
996 latest_source_info_.Update({expr->position(), true}); | 976 latest_source_info_.Update({expr->position(), true}); |
997 } | 977 } |
998 | 978 |
999 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { | 979 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { |
1000 return temporary_register_allocator()->RegisterIsLive(reg); | 980 return temporary_register_allocator()->RegisterIsLive(reg); |
1001 } | 981 } |
1002 | 982 |
1003 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, | 983 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, |
1004 OperandScale operand_scale, | 984 OperandScale operand_scale, |
1005 int operand_index, | 985 int operand_index, |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1292 } | 1272 } |
1293 | 1273 |
1294 uint32_t BytecodeArrayBuilder::UnsignedOperand(size_t value) { | 1274 uint32_t BytecodeArrayBuilder::UnsignedOperand(size_t value) { |
1295 DCHECK_LE(value, kMaxUInt32); | 1275 DCHECK_LE(value, kMaxUInt32); |
1296 return static_cast<uint32_t>(value); | 1276 return static_cast<uint32_t>(value); |
1297 } | 1277 } |
1298 | 1278 |
1299 } // namespace interpreter | 1279 } // namespace interpreter |
1300 } // namespace internal | 1280 } // namespace internal |
1301 } // namespace v8 | 1281 } // namespace v8 |
OLD | NEW |