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) { |
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 fixed_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, fixed_register_count, |
26 handler_table); | 26 parameter_count, handler_table); |
27 } | 27 } |
28 | 28 |
29 // override | 29 // override |
30 void BytecodePeepholeOptimizer::BindLabel(BytecodeLabel* label) { | 30 void BytecodePeepholeOptimizer::BindLabel(BytecodeLabel* label) { |
31 Flush(); | 31 Flush(); |
32 next_stage_->BindLabel(label); | 32 next_stage_->BindLabel(label); |
33 } | 33 } |
34 | 34 |
35 // override | 35 // override |
36 void BytecodePeepholeOptimizer::BindLabel(const BytecodeLabel& target, | 36 void BytecodePeepholeOptimizer::BindLabel(const BytecodeLabel& target, |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 current->set_bytecode(Bytecode::kLdar, current->operand(0)); | 135 current->set_bytecode(Bytecode::kLdar, current->operand(0)); |
136 } | 136 } |
137 | 137 |
138 void TransformLdaSmiBinaryOpToBinaryOpWithSmi(Bytecode new_bytecode, | 138 void TransformLdaSmiBinaryOpToBinaryOpWithSmi(Bytecode new_bytecode, |
139 BytecodeNode* const last, | 139 BytecodeNode* const last, |
140 BytecodeNode* const current) { | 140 BytecodeNode* const current) { |
141 DCHECK_EQ(last->bytecode(), Bytecode::kLdaSmi); | 141 DCHECK_EQ(last->bytecode(), Bytecode::kLdaSmi); |
142 current->set_bytecode(new_bytecode, last->operand(0), current->operand(0), | 142 current->set_bytecode(new_bytecode, last->operand(0), current->operand(0), |
143 current->operand(1)); | 143 current->operand(1)); |
144 if (last->source_info().is_valid()) { | 144 if (last->source_info().is_valid()) { |
145 current->source_info_ptr()->Clone(last->source_info()); | 145 current->source_info().Clone(last->source_info()); |
146 } | 146 } |
147 } | 147 } |
148 | 148 |
149 void TransformLdaZeroBinaryOpToBinaryOpWithZero(Bytecode new_bytecode, | 149 void TransformLdaZeroBinaryOpToBinaryOpWithZero(Bytecode new_bytecode, |
150 BytecodeNode* const last, | 150 BytecodeNode* const last, |
151 BytecodeNode* const current) { | 151 BytecodeNode* const current) { |
152 DCHECK_EQ(last->bytecode(), Bytecode::kLdaZero); | 152 DCHECK_EQ(last->bytecode(), Bytecode::kLdaZero); |
153 current->set_bytecode(new_bytecode, 0, current->operand(0), | 153 current->set_bytecode(new_bytecode, 0, current->operand(0), |
154 current->operand(1)); | 154 current->operand(1)); |
155 if (last->source_info().is_valid()) { | 155 if (last->source_info().is_valid()) { |
156 current->source_info_ptr()->Clone(last->source_info()); | 156 current->source_info().Clone(last->source_info()); |
157 } | 157 } |
158 } | 158 } |
159 | 159 |
160 } // namespace | 160 } // namespace |
161 | 161 |
162 void BytecodePeepholeOptimizer::DefaultAction( | 162 void BytecodePeepholeOptimizer::DefaultAction( |
163 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 163 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
164 DCHECK(LastIsValid()); | 164 DCHECK(LastIsValid()); |
165 DCHECK(!Bytecodes::IsJump(node->bytecode())); | 165 DCHECK(!Bytecodes::IsJump(node->bytecode())); |
166 | 166 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 void BytecodePeepholeOptimizer::ElideLastAction( | 216 void BytecodePeepholeOptimizer::ElideLastAction( |
217 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 217 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
218 DCHECK(LastIsValid()); | 218 DCHECK(LastIsValid()); |
219 DCHECK(!Bytecodes::IsJump(node->bytecode())); | 219 DCHECK(!Bytecodes::IsJump(node->bytecode())); |
220 | 220 |
221 if (CanElideLastBasedOnSourcePosition(node)) { | 221 if (CanElideLastBasedOnSourcePosition(node)) { |
222 if (last()->source_info().is_valid()) { | 222 if (last()->source_info().is_valid()) { |
223 // |node| can not have a valid source position if the source | 223 // |node| can not have a valid source position if the source |
224 // position of last() is valid (per rules in | 224 // position of last() is valid (per rules in |
225 // CanElideLastBasedOnSourcePosition()). | 225 // CanElideLastBasedOnSourcePosition()). |
226 node->source_info_ptr()->Clone(last()->source_info()); | 226 node->source_info().Clone(last()->source_info()); |
227 } | 227 } |
228 SetLast(node); | 228 SetLast(node); |
229 } else { | 229 } else { |
230 DefaultAction(node); | 230 DefaultAction(node); |
231 } | 231 } |
232 } | 232 } |
233 | 233 |
234 void BytecodePeepholeOptimizer::ChangeBytecodeAction( | 234 void BytecodePeepholeOptimizer::ChangeBytecodeAction( |
235 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 235 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
236 DCHECK(LastIsValid()); | 236 DCHECK(LastIsValid()); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 } | 307 } |
308 | 308 |
309 void BytecodePeepholeOptimizer::ElideLastBeforeJumpAction( | 309 void BytecodePeepholeOptimizer::ElideLastBeforeJumpAction( |
310 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 310 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
311 DCHECK(LastIsValid()); | 311 DCHECK(LastIsValid()); |
312 DCHECK(Bytecodes::IsJump(node->bytecode())); | 312 DCHECK(Bytecodes::IsJump(node->bytecode())); |
313 | 313 |
314 if (!CanElideLastBasedOnSourcePosition(node)) { | 314 if (!CanElideLastBasedOnSourcePosition(node)) { |
315 next_stage()->Write(last()); | 315 next_stage()->Write(last()); |
316 } else if (!node->source_info().is_valid()) { | 316 } else if (!node->source_info().is_valid()) { |
317 node->source_info_ptr()->Clone(last()->source_info()); | 317 node->source_info().Clone(last()->source_info()); |
318 } | 318 } |
319 InvalidateLast(); | 319 InvalidateLast(); |
320 } | 320 } |
321 | 321 |
322 void BytecodePeepholeOptimizer::ApplyPeepholeAction(BytecodeNode* const node) { | 322 void BytecodePeepholeOptimizer::ApplyPeepholeAction(BytecodeNode* const node) { |
323 // A single table is used for looking up peephole optimization | 323 // A single table is used for looking up peephole optimization |
324 // matches as it is observed to have better performance. This is | 324 // matches as it is observed to have better performance. This is |
325 // inspite of the fact that jump bytecodes and non-jump bytecodes | 325 // inspite of the fact that jump bytecodes and non-jump bytecodes |
326 // have different processing logic, in particular a jump bytecode | 326 // have different processing logic, in particular a jump bytecode |
327 // always needs to emit the jump via WriteJump(). | 327 // always needs to emit the jump via WriteJump(). |
328 const PeepholeActionAndData* const action_data = | 328 const PeepholeActionAndData* const action_data = |
329 PeepholeActionTable::Lookup(last()->bytecode(), node->bytecode()); | 329 PeepholeActionTable::Lookup(last()->bytecode(), node->bytecode()); |
330 switch (action_data->action) { | 330 switch (action_data->action) { |
331 #define CASE(Action) \ | 331 #define CASE(Action) \ |
332 case PeepholeAction::k##Action: \ | 332 case PeepholeAction::k##Action: \ |
333 Action(node, action_data); \ | 333 Action(node, action_data); \ |
334 break; | 334 break; |
335 PEEPHOLE_ACTION_LIST(CASE) | 335 PEEPHOLE_ACTION_LIST(CASE) |
336 #undef CASE | 336 #undef CASE |
337 default: | 337 default: |
338 UNREACHABLE(); | 338 UNREACHABLE(); |
339 break; | 339 break; |
340 } | 340 } |
341 } | 341 } |
342 | 342 |
343 } // namespace interpreter | 343 } // namespace interpreter |
344 } // namespace internal | 344 } // namespace internal |
345 } // namespace v8 | 345 } // namespace v8 |
OLD | NEW |