OLD | NEW |
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-peephole-optimizer.h" | 5 #include "src/interpreter/bytecode-peephole-optimizer.h" |
6 | 6 |
7 #include "src/objects-inl.h" | 7 #include "src/objects-inl.h" |
8 #include "src/objects.h" | 8 #include "src/objects.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
11 namespace internal { | 11 namespace internal { |
12 namespace interpreter { | 12 namespace interpreter { |
13 | 13 |
14 BytecodePeepholeOptimizer::BytecodePeepholeOptimizer( | 14 BytecodePeepholeOptimizer::BytecodePeepholeOptimizer( |
15 BytecodePipelineStage* next_stage) | 15 BytecodePipelineStage* next_stage) |
16 : next_stage_(next_stage), last_(Bytecode::kIllegal) { | 16 : next_stage_(next_stage), last_(Bytecode::kIllegal, BytecodeSourceInfo()) { |
17 InvalidateLast(); | 17 InvalidateLast(); |
18 } | 18 } |
19 | 19 |
20 // override | 20 // override |
21 Handle<BytecodeArray> BytecodePeepholeOptimizer::ToBytecodeArray( | 21 Handle<BytecodeArray> BytecodePeepholeOptimizer::ToBytecodeArray( |
22 Isolate* isolate, int register_count, int parameter_count, | 22 Isolate* isolate, int register_count, int parameter_count, |
23 Handle<FixedArray> handler_table) { | 23 Handle<FixedArray> handler_table) { |
24 Flush(); | 24 Flush(); |
25 return next_stage_->ToBytecodeArray(isolate, register_count, parameter_count, | 25 return next_stage_->ToBytecodeArray(isolate, register_count, parameter_count, |
26 handler_table); | 26 handler_table); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 | 70 |
71 bool BytecodePeepholeOptimizer::LastIsValid() const { | 71 bool BytecodePeepholeOptimizer::LastIsValid() const { |
72 return last_.bytecode() != Bytecode::kIllegal; | 72 return last_.bytecode() != Bytecode::kIllegal; |
73 } | 73 } |
74 | 74 |
75 void BytecodePeepholeOptimizer::SetLast(const BytecodeNode* const node) { | 75 void BytecodePeepholeOptimizer::SetLast(const BytecodeNode* const node) { |
76 // An action shouldn't leave a NOP as last bytecode unless it has | 76 // An action shouldn't leave a NOP as last bytecode unless it has |
77 // source position information. NOP without source information can | 77 // source position information. NOP without source information can |
78 // always be elided. | 78 // always be elided. |
79 DCHECK(node->bytecode() != Bytecode::kNop || node->source_info().is_valid()); | 79 DCHECK(node->bytecode() != Bytecode::kNop || node->source_info().is_valid()); |
80 | 80 last_ = *node; |
81 last_.Clone(node); | |
82 } | 81 } |
83 | 82 |
84 bool BytecodePeepholeOptimizer::CanElideLastBasedOnSourcePosition( | 83 bool BytecodePeepholeOptimizer::CanElideLastBasedOnSourcePosition( |
85 const BytecodeNode* const current) const { | 84 const BytecodeNode* const current) const { |
86 // | 85 // |
87 // The rules for allowing the elision of the last bytecode based | 86 // The rules for allowing the elision of the last bytecode based |
88 // on source position are: | 87 // on source position are: |
89 // | 88 // |
90 // C U R R E N T | 89 // C U R R E N T |
91 // +--------+--------+--------+ | 90 // +--------+--------+--------+ |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 current->set_bytecode(Bytecode::kLdar, current->operand(0)); | 134 current->set_bytecode(Bytecode::kLdar, current->operand(0)); |
136 } | 135 } |
137 | 136 |
138 void TransformLdaSmiBinaryOpToBinaryOpWithSmi(Bytecode new_bytecode, | 137 void TransformLdaSmiBinaryOpToBinaryOpWithSmi(Bytecode new_bytecode, |
139 BytecodeNode* const last, | 138 BytecodeNode* const last, |
140 BytecodeNode* const current) { | 139 BytecodeNode* const current) { |
141 DCHECK_EQ(last->bytecode(), Bytecode::kLdaSmi); | 140 DCHECK_EQ(last->bytecode(), Bytecode::kLdaSmi); |
142 current->set_bytecode(new_bytecode, last->operand(0), current->operand(0), | 141 current->set_bytecode(new_bytecode, last->operand(0), current->operand(0), |
143 current->operand(1)); | 142 current->operand(1)); |
144 if (last->source_info().is_valid()) { | 143 if (last->source_info().is_valid()) { |
145 current->source_info_ptr()->Clone(last->source_info()); | 144 current->set_source_info(last->source_info()); |
146 } | 145 } |
147 } | 146 } |
148 | 147 |
149 void TransformLdaZeroBinaryOpToBinaryOpWithZero(Bytecode new_bytecode, | 148 void TransformLdaZeroBinaryOpToBinaryOpWithZero(Bytecode new_bytecode, |
150 BytecodeNode* const last, | 149 BytecodeNode* const last, |
151 BytecodeNode* const current) { | 150 BytecodeNode* const current) { |
152 DCHECK_EQ(last->bytecode(), Bytecode::kLdaZero); | 151 DCHECK_EQ(last->bytecode(), Bytecode::kLdaZero); |
153 current->set_bytecode(new_bytecode, 0, current->operand(0), | 152 current->set_bytecode(new_bytecode, 0, current->operand(0), |
154 current->operand(1)); | 153 current->operand(1)); |
155 if (last->source_info().is_valid()) { | 154 if (last->source_info().is_valid()) { |
156 current->source_info_ptr()->Clone(last->source_info()); | 155 current->set_source_info(last->source_info()); |
157 } | 156 } |
158 } | 157 } |
159 | 158 |
160 } // namespace | 159 } // namespace |
161 | 160 |
162 void BytecodePeepholeOptimizer::DefaultAction( | 161 void BytecodePeepholeOptimizer::DefaultAction( |
163 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 162 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
164 DCHECK(LastIsValid()); | 163 DCHECK(LastIsValid()); |
165 DCHECK(!Bytecodes::IsJump(node->bytecode())); | 164 DCHECK(!Bytecodes::IsJump(node->bytecode())); |
166 | 165 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 void BytecodePeepholeOptimizer::ElideLastAction( | 215 void BytecodePeepholeOptimizer::ElideLastAction( |
217 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 216 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
218 DCHECK(LastIsValid()); | 217 DCHECK(LastIsValid()); |
219 DCHECK(!Bytecodes::IsJump(node->bytecode())); | 218 DCHECK(!Bytecodes::IsJump(node->bytecode())); |
220 | 219 |
221 if (CanElideLastBasedOnSourcePosition(node)) { | 220 if (CanElideLastBasedOnSourcePosition(node)) { |
222 if (last()->source_info().is_valid()) { | 221 if (last()->source_info().is_valid()) { |
223 // |node| can not have a valid source position if the source | 222 // |node| can not have a valid source position if the source |
224 // position of last() is valid (per rules in | 223 // position of last() is valid (per rules in |
225 // CanElideLastBasedOnSourcePosition()). | 224 // CanElideLastBasedOnSourcePosition()). |
226 node->source_info_ptr()->Clone(last()->source_info()); | 225 node->set_source_info(last()->source_info()); |
227 } | 226 } |
228 SetLast(node); | 227 SetLast(node); |
229 } else { | 228 } else { |
230 DefaultAction(node); | 229 DefaultAction(node); |
231 } | 230 } |
232 } | 231 } |
233 | 232 |
234 void BytecodePeepholeOptimizer::ChangeBytecodeAction( | 233 void BytecodePeepholeOptimizer::ChangeBytecodeAction( |
235 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 234 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
236 DCHECK(LastIsValid()); | 235 DCHECK(LastIsValid()); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 } | 306 } |
308 | 307 |
309 void BytecodePeepholeOptimizer::ElideLastBeforeJumpAction( | 308 void BytecodePeepholeOptimizer::ElideLastBeforeJumpAction( |
310 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 309 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
311 DCHECK(LastIsValid()); | 310 DCHECK(LastIsValid()); |
312 DCHECK(Bytecodes::IsJump(node->bytecode())); | 311 DCHECK(Bytecodes::IsJump(node->bytecode())); |
313 | 312 |
314 if (!CanElideLastBasedOnSourcePosition(node)) { | 313 if (!CanElideLastBasedOnSourcePosition(node)) { |
315 next_stage()->Write(last()); | 314 next_stage()->Write(last()); |
316 } else if (!node->source_info().is_valid()) { | 315 } else if (!node->source_info().is_valid()) { |
317 node->source_info_ptr()->Clone(last()->source_info()); | 316 node->set_source_info(last()->source_info()); |
318 } | 317 } |
319 InvalidateLast(); | 318 InvalidateLast(); |
320 } | 319 } |
321 | 320 |
322 void BytecodePeepholeOptimizer::ApplyPeepholeAction(BytecodeNode* const node) { | 321 void BytecodePeepholeOptimizer::ApplyPeepholeAction(BytecodeNode* const node) { |
323 // A single table is used for looking up peephole optimization | 322 // A single table is used for looking up peephole optimization |
324 // matches as it is observed to have better performance. This is | 323 // matches as it is observed to have better performance. This is |
325 // inspite of the fact that jump bytecodes and non-jump bytecodes | 324 // inspite of the fact that jump bytecodes and non-jump bytecodes |
326 // have different processing logic, in particular a jump bytecode | 325 // have different processing logic, in particular a jump bytecode |
327 // always needs to emit the jump via WriteJump(). | 326 // always needs to emit the jump via WriteJump(). |
328 const PeepholeActionAndData* const action_data = | 327 const PeepholeActionAndData* const action_data = |
329 PeepholeActionTable::Lookup(last()->bytecode(), node->bytecode()); | 328 PeepholeActionTable::Lookup(last()->bytecode(), node->bytecode()); |
330 switch (action_data->action) { | 329 switch (action_data->action) { |
331 #define CASE(Action) \ | 330 #define CASE(Action) \ |
332 case PeepholeAction::k##Action: \ | 331 case PeepholeAction::k##Action: \ |
333 Action(node, action_data); \ | 332 Action(node, action_data); \ |
334 break; | 333 break; |
335 PEEPHOLE_ACTION_LIST(CASE) | 334 PEEPHOLE_ACTION_LIST(CASE) |
336 #undef CASE | 335 #undef CASE |
337 default: | 336 default: |
338 UNREACHABLE(); | 337 UNREACHABLE(); |
339 break; | 338 break; |
340 } | 339 } |
341 } | 340 } |
342 | 341 |
343 } // namespace interpreter | 342 } // namespace interpreter |
344 } // namespace internal | 343 } // namespace internal |
345 } // namespace v8 | 344 } // namespace v8 |
OLD | NEW |