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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 // values. Only the first bytecode is needed if there's a sequence | 118 // values. Only the first bytecode is needed if there's a sequence |
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) current is Nop. |
| 129 // (ii) ToNumber if the last puts a number in the accumulator. |
129 return false; | 130 return false; |
130 } | 131 } |
131 } | 132 } |
132 | 133 |
133 bool BytecodePeepholeOptimizer::CanElideLastBasedOnSourcePosition( | 134 bool BytecodePeepholeOptimizer::CanElideLastBasedOnSourcePosition( |
134 const BytecodeNode* const current) const { | 135 const BytecodeNode* const current) const { |
135 // | 136 // |
136 // The rules for allowing the elision of the last bytecode based | 137 // The rules for allowing the elision of the last bytecode based |
137 // on source position are: | 138 // on source position are: |
138 // | 139 // |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 // Star R ====/ Ldar R | 182 // Star R ====/ Ldar R |
182 // | 183 // |
183 // which loads a global value into both a register and the | 184 // which loads a global value into both a register and the |
184 // accumulator. However, in the second form the Ldar can often be | 185 // accumulator. However, in the second form the Ldar can often be |
185 // peephole optimized away unlike the Star in the first form. | 186 // peephole optimized away unlike the Star in the first form. |
186 // | 187 // |
187 last->Transform(new_bytecode, current->operand(0)); | 188 last->Transform(new_bytecode, current->operand(0)); |
188 current->set_bytecode(Bytecode::kLdar, current->operand(0)); | 189 current->set_bytecode(Bytecode::kLdar, current->operand(0)); |
189 } | 190 } |
190 | 191 |
| 192 void TransformToBinaryOpWithSmiOnRhs(Bytecode new_bytecode, |
| 193 BytecodeNode* const last, |
| 194 BytecodeNode* const current) { |
| 195 DCHECK(Bytecodes::IsLdaSmiOrLdaZero(last->bytecode())); |
| 196 uint32_t imm_operand = |
| 197 last->bytecode() == Bytecode::kLdaSmi ? last->operand(0) : 0; |
| 198 current->set_bytecode(new_bytecode, imm_operand, current->operand(0)); |
| 199 if (last->source_info().is_valid()) { |
| 200 current->source_info().Clone(last->source_info()); |
| 201 } |
| 202 } |
| 203 |
191 } // namespace | 204 } // namespace |
192 | 205 |
193 bool BytecodePeepholeOptimizer::TransformLastAndCurrentBytecodes( | 206 bool BytecodePeepholeOptimizer::TransformLastAndCurrentBytecodes( |
194 BytecodeNode* const current) { | 207 BytecodeNode* const current) { |
195 if (current->bytecode() == Bytecode::kStar && | 208 if (current->bytecode() == Bytecode::kStar && |
196 !current->source_info().is_statement()) { | 209 !current->source_info().is_statement()) { |
197 // Note: If the Star is tagged with a statement position, we can't | 210 // Note: If the Star is tagged with a statement position, we can't |
198 // perform this transform as the store to the register will | 211 // perform this transform as the store to the register will |
199 // have the wrong ordering for stepping in the debugger. | 212 // have the wrong ordering for stepping in the debugger. |
200 switch (last_.bytecode()) { | 213 switch (last_.bytecode()) { |
201 case Bytecode::kLdaNamedProperty: | 214 case Bytecode::kLdaNamedProperty: |
202 TransformLdaStarToLdrLdar(Bytecode::kLdrNamedProperty, &last_, current); | 215 TransformLdaStarToLdrLdar(Bytecode::kLdrNamedProperty, &last_, current); |
203 return true; | 216 return true; |
204 case Bytecode::kLdaKeyedProperty: | 217 case Bytecode::kLdaKeyedProperty: |
205 TransformLdaStarToLdrLdar(Bytecode::kLdrKeyedProperty, &last_, current); | 218 TransformLdaStarToLdrLdar(Bytecode::kLdrKeyedProperty, &last_, current); |
206 return true; | 219 return true; |
207 case Bytecode::kLdaGlobal: | 220 case Bytecode::kLdaGlobal: |
208 TransformLdaStarToLdrLdar(Bytecode::kLdrGlobal, &last_, current); | 221 TransformLdaStarToLdrLdar(Bytecode::kLdrGlobal, &last_, current); |
209 return true; | 222 return true; |
210 case Bytecode::kLdaContextSlot: | 223 case Bytecode::kLdaContextSlot: |
211 TransformLdaStarToLdrLdar(Bytecode::kLdrContextSlot, &last_, current); | 224 TransformLdaStarToLdrLdar(Bytecode::kLdrContextSlot, &last_, current); |
212 return true; | 225 return true; |
213 case Bytecode::kLdaUndefined: | 226 case Bytecode::kLdaUndefined: |
214 TransformLdaStarToLdrLdar(Bytecode::kLdrUndefined, &last_, current); | 227 TransformLdaStarToLdrLdar(Bytecode::kLdrUndefined, &last_, current); |
215 return true; | 228 return true; |
216 default: | 229 default: |
217 break; | 230 break; |
218 } | 231 } |
| 232 } else if (Bytecodes::IsLdaSmiOrLdaZero(last_.bytecode()) && |
| 233 (!last_.source_info().is_valid() || |
| 234 !current->source_info().is_valid())) { |
| 235 switch (current->bytecode()) { |
| 236 case Bytecode::kAdd: |
| 237 TransformToBinaryOpWithSmiOnRhs(Bytecode::kAddSmi, &last_, current); |
| 238 InvalidateLast(); |
| 239 return true; |
| 240 case Bytecode::kSub: |
| 241 TransformToBinaryOpWithSmiOnRhs(Bytecode::kSubSmi, &last_, current); |
| 242 InvalidateLast(); |
| 243 return true; |
| 244 case Bytecode::kBitwiseOr: |
| 245 TransformToBinaryOpWithSmiOnRhs(Bytecode::kBitwiseOrSmi, &last_, |
| 246 current); |
| 247 InvalidateLast(); |
| 248 return true; |
| 249 case Bytecode::kBitwiseAnd: |
| 250 TransformToBinaryOpWithSmiOnRhs(Bytecode::kBitwiseAndSmi, &last_, |
| 251 current); |
| 252 InvalidateLast(); |
| 253 return true; |
| 254 case Bytecode::kShiftLeft: |
| 255 TransformToBinaryOpWithSmiOnRhs(Bytecode::kShiftLeftSmi, &last_, |
| 256 current); |
| 257 InvalidateLast(); |
| 258 return true; |
| 259 case Bytecode::kShiftRight: |
| 260 TransformToBinaryOpWithSmiOnRhs(Bytecode::kShiftRightSmi, &last_, |
| 261 current); |
| 262 InvalidateLast(); |
| 263 return true; |
| 264 default: |
| 265 break; |
| 266 } |
219 } | 267 } |
| 268 |
220 return false; | 269 return false; |
221 } | 270 } |
222 | 271 |
223 bool BytecodePeepholeOptimizer::RemoveToBooleanFromJump( | 272 bool BytecodePeepholeOptimizer::RemoveToBooleanFromJump( |
224 BytecodeNode* const current) { | 273 BytecodeNode* const current) { |
225 bool can_remove = Bytecodes::IsJumpIfToBoolean(current->bytecode()) && | 274 bool can_remove = Bytecodes::IsJumpIfToBoolean(current->bytecode()) && |
226 Bytecodes::WritesBooleanToAccumulator(last_.bytecode()); | 275 Bytecodes::WritesBooleanToAccumulator(last_.bytecode()); |
227 if (can_remove) { | 276 if (can_remove) { |
228 // Conditional jumps with boolean conditions are emiitted in | 277 // Conditional jumps with boolean conditions are emiitted in |
229 // ToBoolean form by the bytecode array builder, | 278 // 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 | 321 // The current instruction clobbers the accumulator without reading it. The |
273 // load in the last instruction can be elided as it has no effect. | 322 // load in the last instruction can be elided as it has no effect. |
274 return true; | 323 return true; |
275 } else { | 324 } else { |
276 return false; | 325 return false; |
277 } | 326 } |
278 } | 327 } |
279 | 328 |
280 BytecodeNode* BytecodePeepholeOptimizer::Optimize(BytecodeNode* current) { | 329 BytecodeNode* BytecodePeepholeOptimizer::Optimize(BytecodeNode* current) { |
281 TryToRemoveLastExpressionPosition(current); | 330 TryToRemoveLastExpressionPosition(current); |
282 | |
283 if (TransformCurrentBytecode(current) || | 331 if (TransformCurrentBytecode(current) || |
284 TransformLastAndCurrentBytecodes(current)) { | 332 TransformLastAndCurrentBytecodes(current)) { |
285 return current; | 333 return current; |
286 } | 334 } |
287 | 335 |
288 if (CanElideCurrent(current)) { | 336 if (CanElideCurrent(current)) { |
289 if (current->source_info().is_valid()) { | 337 if (current->source_info().is_valid()) { |
290 // Preserve the source information by replacing the current bytecode | 338 // Preserve the source information by replacing the current bytecode |
291 // with a no op bytecode. | 339 // with a no op bytecode. |
292 current->set_bytecode(Bytecode::kNop); | 340 current->set_bytecode(Bytecode::kNop); |
(...skipping 25 matching lines...) Expand all Loading... |
318 next_stage_->Write(&last_); | 366 next_stage_->Write(&last_); |
319 InvalidateLast(); | 367 InvalidateLast(); |
320 } | 368 } |
321 } | 369 } |
322 return current; | 370 return current; |
323 } | 371 } |
324 | 372 |
325 } // namespace interpreter | 373 } // namespace interpreter |
326 } // namespace internal | 374 } // namespace internal |
327 } // namespace v8 | 375 } // namespace v8 |
OLD | NEW |