OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of ssa; | 5 part of ssa; |
6 | 6 |
7 /** | 7 /** |
8 * [InvokeDynamicSpecializer] and its subclasses are helpers to | 8 * [InvokeDynamicSpecializer] and its subclasses are helpers to |
9 * optimize intercepted dynamic calls. It knows what input types | 9 * optimize intercepted dynamic calls. It knows what input types |
10 * would be beneficial for performance, and how to change a invoke | 10 * would be beneficial for performance, and how to change a invoke |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 } | 201 } |
202 | 202 |
203 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 203 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
204 Compiler compiler) { | 204 Compiler compiler) { |
205 if (isBuiltin(instruction, compiler)) { | 205 if (isBuiltin(instruction, compiler)) { |
206 HInstruction builtin = newBuiltinVariant(instruction, compiler); | 206 HInstruction builtin = newBuiltinVariant(instruction, compiler); |
207 if (builtin != null) return builtin; | 207 if (builtin != null) return builtin; |
208 // Even if there is no builtin equivalent instruction, we know | 208 // Even if there is no builtin equivalent instruction, we know |
209 // the instruction does not have any side effect, and that it | 209 // the instruction does not have any side effect, and that it |
210 // can be GVN'ed. | 210 // can be GVN'ed. |
211 instruction.sideEffects.clearAllSideEffects(); | 211 clearAllSideEffects(instruction); |
212 instruction.sideEffects.clearAllDependencies(); | |
213 instruction.setUseGvn(); | |
214 } | 212 } |
215 return null; | 213 return null; |
216 } | 214 } |
| 215 |
| 216 void clearAllSideEffects(HInstruction instruction) { |
| 217 instruction.sideEffects.clearAllSideEffects(); |
| 218 instruction.sideEffects.clearAllDependencies(); |
| 219 instruction.setUseGvn(); |
| 220 } |
217 | 221 |
218 HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler); | 222 HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler); |
219 } | 223 } |
220 | 224 |
221 class AddSpecializer extends BinaryArithmeticSpecializer { | 225 class AddSpecializer extends BinaryArithmeticSpecializer { |
222 const AddSpecializer(); | 226 const AddSpecializer(); |
223 | 227 |
224 BinaryOperation operation(ConstantSystem constantSystem) { | 228 BinaryOperation operation(ConstantSystem constantSystem) { |
225 return constantSystem.add; | 229 return constantSystem.add; |
226 } | 230 } |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 Compiler compiler) { | 328 Compiler compiler) { |
325 // All bitwise operations on primitive types either produce an | 329 // All bitwise operations on primitive types either produce an |
326 // integer or throw an error. | 330 // integer or throw an error. |
327 HInstruction left = instruction.inputs[1]; | 331 HInstruction left = instruction.inputs[1]; |
328 JavaScriptBackend backend = compiler.backend; | 332 JavaScriptBackend backend = compiler.backend; |
329 if (left.isPrimitiveOrNull(compiler)) { | 333 if (left.isPrimitiveOrNull(compiler)) { |
330 return backend.intType; | 334 return backend.intType; |
331 } | 335 } |
332 return super.computeTypeFromInputTypes(instruction, compiler); | 336 return super.computeTypeFromInputTypes(instruction, compiler); |
333 } | 337 } |
| 338 |
| 339 bool argumentLessThan32(HInstruction instruction) { |
| 340 if (!instruction.isConstantInteger()) return false; |
| 341 HConstant rightConstant = instruction; |
| 342 IntConstant intConstant = rightConstant.constant; |
| 343 int count = intConstant.value; |
| 344 return count >= 0 && count <= 31; |
| 345 } |
| 346 |
| 347 bool isPositive(HInstruction instruction) { |
| 348 // TODO: We should use the value range analysis. Currently, ranges |
| 349 // are discarded just after the analysis. |
| 350 return instruction is HBinaryBitOp; |
| 351 } |
334 } | 352 } |
335 | 353 |
336 class ShiftLeftSpecializer extends BinaryBitOpSpecializer { | 354 class ShiftLeftSpecializer extends BinaryBitOpSpecializer { |
337 const ShiftLeftSpecializer(); | 355 const ShiftLeftSpecializer(); |
338 | 356 |
339 BinaryOperation operation(ConstantSystem constantSystem) { | 357 BinaryOperation operation(ConstantSystem constantSystem) { |
340 return constantSystem.shiftLeft; | 358 return constantSystem.shiftLeft; |
341 } | 359 } |
342 | 360 |
343 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 361 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
344 Compiler compiler) { | 362 Compiler compiler) { |
345 HInstruction left = instruction.inputs[1]; | 363 HInstruction left = instruction.inputs[1]; |
346 HInstruction right = instruction.inputs[2]; | 364 HInstruction right = instruction.inputs[2]; |
347 if (!left.isNumber(compiler)) return null; | 365 if (left.isNumber(compiler)) { |
348 if (argumentLessThan32(right)) { | 366 if (argumentLessThan32(right)) { |
349 return newBuiltinVariant(instruction, compiler); | 367 return newBuiltinVariant(instruction, compiler); |
| 368 } |
| 369 // Even if there is no builtin equivalent instruction, we know |
| 370 // the instruction does not have any side effect, and that it |
| 371 // can be GVN'ed. |
| 372 clearAllSideEffects(instruction); |
350 } | 373 } |
351 return null; | 374 return null; |
352 } | 375 } |
353 | 376 |
354 HInstruction newBuiltinVariant(HInvokeDynamic instruction, | 377 HInstruction newBuiltinVariant(HInvokeDynamic instruction, |
355 Compiler compiler) { | 378 Compiler compiler) { |
356 JavaScriptBackend backend = compiler.backend; | 379 JavaScriptBackend backend = compiler.backend; |
357 return new HShiftLeft( | 380 return new HShiftLeft( |
358 instruction.inputs[1], instruction.inputs[2], | 381 instruction.inputs[1], instruction.inputs[2], |
359 instruction.selector, backend.intType); | 382 instruction.selector, backend.intType); |
360 } | 383 } |
361 | |
362 bool argumentLessThan32(HInstruction instruction) { | |
363 if (!instruction.isConstantInteger()) return false; | |
364 HConstant rightConstant = instruction; | |
365 IntConstant intConstant = rightConstant.constant; | |
366 int count = intConstant.value; | |
367 return count >= 0 && count <= 31; | |
368 } | |
369 } | 384 } |
370 | 385 |
371 class ShiftRightSpecializer extends BinaryBitOpSpecializer { | 386 class ShiftRightSpecializer extends BinaryBitOpSpecializer { |
372 const ShiftRightSpecializer(); | 387 const ShiftRightSpecializer(); |
373 | 388 |
374 HInstruction newBuiltinVariant(HInvokeDynamic instruction, | 389 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
375 Compiler compiler) { | 390 Compiler compiler) { |
376 // Shift right cannot be mapped to the native operator easily. | 391 HInstruction left = instruction.inputs[1]; |
| 392 HInstruction right = instruction.inputs[2]; |
| 393 if (left.isNumber(compiler)) { |
| 394 if (argumentLessThan32(right) && isPositive(left)) { |
| 395 return newBuiltinVariant(instruction, compiler); |
| 396 } |
| 397 // Even if there is no builtin equivalent instruction, we know |
| 398 // the instruction does not have any side effect, and that it |
| 399 // can be GVN'ed. |
| 400 clearAllSideEffects(instruction); |
| 401 } |
377 return null; | 402 return null; |
378 } | 403 } |
379 | 404 |
| 405 HInstruction newBuiltinVariant(HInvokeDynamic instruction, |
| 406 Compiler compiler) { |
| 407 JavaScriptBackend backend = compiler.backend; |
| 408 return new HShiftRight( |
| 409 instruction.inputs[1], instruction.inputs[2], |
| 410 instruction.selector, backend.intType); |
| 411 } |
| 412 |
380 BinaryOperation operation(ConstantSystem constantSystem) { | 413 BinaryOperation operation(ConstantSystem constantSystem) { |
381 return constantSystem.shiftRight; | 414 return constantSystem.shiftRight; |
382 } | 415 } |
383 } | 416 } |
384 | 417 |
385 class BitOrSpecializer extends BinaryBitOpSpecializer { | 418 class BitOrSpecializer extends BinaryBitOpSpecializer { |
386 const BitOrSpecializer(); | 419 const BitOrSpecializer(); |
387 | 420 |
388 BinaryOperation operation(ConstantSystem constantSystem) { | 421 BinaryOperation operation(ConstantSystem constantSystem) { |
389 return constantSystem.bitOr; | 422 return constantSystem.bitOr; |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 } | 582 } |
550 | 583 |
551 HInstruction newBuiltinVariant(HInvokeDynamic instruction, | 584 HInstruction newBuiltinVariant(HInvokeDynamic instruction, |
552 Compiler compiler) { | 585 Compiler compiler) { |
553 JavaScriptBackend backend = compiler.backend; | 586 JavaScriptBackend backend = compiler.backend; |
554 return new HLessEqual( | 587 return new HLessEqual( |
555 instruction.inputs[1], instruction.inputs[2], | 588 instruction.inputs[1], instruction.inputs[2], |
556 instruction.selector, backend.boolType); | 589 instruction.selector, backend.boolType); |
557 } | 590 } |
558 } | 591 } |
OLD | NEW |