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-peephole-optimizer.h" | 5 #include "src/interpreter/bytecode-peephole-optimizer.h" |
6 | 6 |
7 #include "src/interpreter/constant-array-builder.h" | 7 #include "src/interpreter/constant-array-builder.h" |
8 #include "src/objects-inl.h" | 8 #include "src/objects-inl.h" |
9 #include "src/objects.h" | 9 #include "src/objects.h" |
10 | 10 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
119 // of back-to-back Ldar and Star bytecodes with the same operand. | 119 // of back-to-back Ldar and Star bytecodes with the same operand. |
120 return true; | 120 return true; |
121 } else if (current->bytecode() == Bytecode::kToName && | 121 } else if (current->bytecode() == Bytecode::kToName && |
122 LastBytecodePutsNameInAccumulator()) { | 122 LastBytecodePutsNameInAccumulator()) { |
123 // If the previous bytecode ensured a name was in the accumulator, | 123 // If the previous bytecode ensured a name was in the accumulator, |
124 // the type coercion ToName() can be elided. | 124 // the type coercion ToName() can be elided. |
125 return true; | 125 return true; |
126 } else { | 126 } else { |
127 // Additional candidates for eliding current: | 127 // Additional candidates for eliding current: |
128 // (i) ToNumber if the last puts a number in the accumulator. | 128 // (i) ToNumber if the last puts a number in the accumulator. |
129 return false; | 129 return current->bytecode() == Bytecode::kNop; |
rmcilroy
2016/07/04 12:35:32
Can we do this in a separate CL please, so we can
oth
2016/07/04 14:56:24
Done.
| |
130 } | 130 } |
131 } | 131 } |
132 | 132 |
133 bool BytecodePeepholeOptimizer::CanElideLastBasedOnSourcePosition( | 133 bool BytecodePeepholeOptimizer::CanElideLastBasedOnSourcePosition( |
134 const BytecodeNode* const current) const { | 134 const BytecodeNode* const current) const { |
135 // | 135 // |
136 // The rules for allowing the elision of the last bytecode based | 136 // The rules for allowing the elision of the last bytecode based |
137 // on source position are: | 137 // on source position are: |
138 // | 138 // |
139 // C U R R E N T | 139 // C U R R E N T |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
181 // Star R ====/ Ldar R | 181 // Star R ====/ Ldar R |
182 // | 182 // |
183 // which loads a global value into both a register and the | 183 // which loads a global value into both a register and the |
184 // accumulator. However, in the second form the Ldar can often be | 184 // accumulator. However, in the second form the Ldar can often be |
185 // peephole optimized away unlike the Star in the first form. | 185 // peephole optimized away unlike the Star in the first form. |
186 // | 186 // |
187 last->Transform(new_bytecode, current->operand(0)); | 187 last->Transform(new_bytecode, current->operand(0)); |
188 current->set_bytecode(Bytecode::kLdar, current->operand(0)); | 188 current->set_bytecode(Bytecode::kLdar, current->operand(0)); |
189 } | 189 } |
190 | 190 |
191 void TransformToBinaryOpWithSmiOnRhs(Bytecode new_bytecode, | |
192 BytecodeNode* const last, | |
193 BytecodeNode* const current) { | |
194 uint32_t smi_operand = last->operand(0); | |
195 current->set_bytecode(new_bytecode, smi_operand, current->operand(0)); | |
196 if (last->source_info().is_valid()) { | |
197 current->source_info().Clone(last->source_info()); | |
198 } | |
199 } | |
200 | |
191 } // namespace | 201 } // namespace |
192 | 202 |
193 bool BytecodePeepholeOptimizer::TransformLastAndCurrentBytecodes( | 203 bool BytecodePeepholeOptimizer::TransformLastAndCurrentBytecodes( |
194 BytecodeNode* const current) { | 204 BytecodeNode* const current) { |
195 if (current->bytecode() == Bytecode::kStar && | 205 if (current->bytecode() == Bytecode::kStar && |
196 !current->source_info().is_statement()) { | 206 !current->source_info().is_statement()) { |
197 // Note: If the Star is tagged with a statement position, we can't | 207 // Note: If the Star is tagged with a statement position, we can't |
198 // perform this transform as the store to the register will | 208 // perform this transform as the store to the register will |
199 // have the wrong ordering for stepping in the debugger. | 209 // have the wrong ordering for stepping in the debugger. |
200 switch (last_.bytecode()) { | 210 switch (last_.bytecode()) { |
201 case Bytecode::kLdaNamedProperty: | 211 case Bytecode::kLdaNamedProperty: |
202 TransformLdaStarToLdrLdar(Bytecode::kLdrNamedProperty, &last_, current); | 212 TransformLdaStarToLdrLdar(Bytecode::kLdrNamedProperty, &last_, current); |
203 return true; | 213 return true; |
204 case Bytecode::kLdaKeyedProperty: | 214 case Bytecode::kLdaKeyedProperty: |
205 TransformLdaStarToLdrLdar(Bytecode::kLdrKeyedProperty, &last_, current); | 215 TransformLdaStarToLdrLdar(Bytecode::kLdrKeyedProperty, &last_, current); |
206 return true; | 216 return true; |
207 case Bytecode::kLdaGlobal: | 217 case Bytecode::kLdaGlobal: |
208 TransformLdaStarToLdrLdar(Bytecode::kLdrGlobal, &last_, current); | 218 TransformLdaStarToLdrLdar(Bytecode::kLdrGlobal, &last_, current); |
209 return true; | 219 return true; |
210 case Bytecode::kLdaContextSlot: | 220 case Bytecode::kLdaContextSlot: |
211 TransformLdaStarToLdrLdar(Bytecode::kLdrContextSlot, &last_, current); | 221 TransformLdaStarToLdrLdar(Bytecode::kLdrContextSlot, &last_, current); |
212 return true; | 222 return true; |
213 case Bytecode::kLdaUndefined: | 223 case Bytecode::kLdaUndefined: |
214 TransformLdaStarToLdrLdar(Bytecode::kLdrUndefined, &last_, current); | 224 TransformLdaStarToLdrLdar(Bytecode::kLdrUndefined, &last_, current); |
215 return true; | 225 return true; |
216 default: | 226 default: |
217 break; | 227 break; |
218 } | 228 } |
229 } else if (last_.bytecode() == Bytecode::kLdaSmi && | |
230 (!last_.source_info().is_valid() || | |
231 !current->source_info().is_valid())) { | |
232 switch (current->bytecode()) { | |
233 case Bytecode::kAdd: | |
234 TransformToBinaryOpWithSmiOnRhs(Bytecode::kAddSmi, &last_, current); | |
235 InvalidateLast(); | |
236 return true; | |
237 case Bytecode::kSub: | |
238 TransformToBinaryOpWithSmiOnRhs(Bytecode::kSubSmi, &last_, current); | |
239 InvalidateLast(); | |
240 return true; | |
241 case Bytecode::kBitwiseOr: | |
242 TransformToBinaryOpWithSmiOnRhs(Bytecode::kBitwiseOrSmi, &last_, | |
243 current); | |
244 InvalidateLast(); | |
245 return true; | |
246 case Bytecode::kBitwiseAnd: | |
247 TransformToBinaryOpWithSmiOnRhs(Bytecode::kBitwiseAndSmi, &last_, | |
248 current); | |
249 InvalidateLast(); | |
250 return true; | |
251 case Bytecode::kShiftLeft: | |
252 TransformToBinaryOpWithSmiOnRhs(Bytecode::kShiftLeftSmi, &last_, | |
253 current); | |
254 InvalidateLast(); | |
255 return true; | |
256 case Bytecode::kShiftRight: | |
257 TransformToBinaryOpWithSmiOnRhs(Bytecode::kShiftRightSmi, &last_, | |
258 current); | |
259 InvalidateLast(); | |
260 return true; | |
261 default: | |
262 break; | |
263 } | |
264 } else if (last_.bytecode() == Bytecode::kLdaZero && | |
rmcilroy
2016/07/04 12:35:32
Can we not also do the LdaZero optimization for al
oth
2016/07/04 14:56:24
Done. This was skipped due to low numbers of occur
| |
265 current->bytecode() == Bytecode::kBitwiseOr && | |
266 !current->source_info().is_valid()) { | |
267 current->set_bytecode(Bytecode::kBitwiseOrSmi, 0, current->operand(0)); | |
268 current->source_info().Clone(last_.source_info()); | |
269 InvalidateLast(); | |
270 return true; | |
219 } | 271 } |
272 | |
220 return false; | 273 return false; |
221 } | 274 } |
222 | 275 |
223 bool BytecodePeepholeOptimizer::RemoveToBooleanFromJump( | 276 bool BytecodePeepholeOptimizer::RemoveToBooleanFromJump( |
224 BytecodeNode* const current) { | 277 BytecodeNode* const current) { |
225 bool can_remove = Bytecodes::IsJumpIfToBoolean(current->bytecode()) && | 278 bool can_remove = Bytecodes::IsJumpIfToBoolean(current->bytecode()) && |
226 Bytecodes::WritesBooleanToAccumulator(last_.bytecode()); | 279 Bytecodes::WritesBooleanToAccumulator(last_.bytecode()); |
227 if (can_remove) { | 280 if (can_remove) { |
228 // Conditional jumps with boolean conditions are emiitted in | 281 // Conditional jumps with boolean conditions are emiitted in |
229 // ToBoolean form by the bytecode array builder, | 282 // ToBoolean form by the bytecode array builder, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
272 // The current instruction clobbers the accumulator without reading it. The | 325 // The current instruction clobbers the accumulator without reading it. The |
273 // load in the last instruction can be elided as it has no effect. | 326 // load in the last instruction can be elided as it has no effect. |
274 return true; | 327 return true; |
275 } else { | 328 } else { |
276 return false; | 329 return false; |
277 } | 330 } |
278 } | 331 } |
279 | 332 |
280 BytecodeNode* BytecodePeepholeOptimizer::Optimize(BytecodeNode* current) { | 333 BytecodeNode* BytecodePeepholeOptimizer::Optimize(BytecodeNode* current) { |
281 TryToRemoveLastExpressionPosition(current); | 334 TryToRemoveLastExpressionPosition(current); |
282 | |
283 if (TransformCurrentBytecode(current) || | 335 if (TransformCurrentBytecode(current) || |
284 TransformLastAndCurrentBytecodes(current)) { | 336 TransformLastAndCurrentBytecodes(current)) { |
285 return current; | 337 return current; |
286 } | 338 } |
287 | 339 |
288 if (CanElideCurrent(current)) { | 340 if (CanElideCurrent(current)) { |
289 if (current->source_info().is_valid()) { | 341 if (current->source_info().is_valid()) { |
290 // Preserve the source information by replacing the current bytecode | 342 // Preserve the source information by replacing the current bytecode |
291 // with a no op bytecode. | 343 // with a no op bytecode. |
292 current->set_bytecode(Bytecode::kNop); | 344 current->set_bytecode(Bytecode::kNop); |
(...skipping 25 matching lines...) Expand all Loading... | |
318 next_stage_->Write(&last_); | 370 next_stage_->Write(&last_); |
319 InvalidateLast(); | 371 InvalidateLast(); |
320 } | 372 } |
321 } | 373 } |
322 return current; | 374 return current; |
323 } | 375 } |
324 | 376 |
325 } // namespace interpreter | 377 } // namespace interpreter |
326 } // namespace internal | 378 } // namespace internal |
327 } // namespace v8 | 379 } // namespace v8 |
OLD | NEW |