| 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 import '../compiler.dart' show Compiler; | 5 import '../compiler.dart' show Compiler; |
| 6 import '../constants/constant_system.dart'; | 6 import '../constants/constant_system.dart'; |
| 7 import '../constants/values.dart'; | 7 import '../constants/values.dart'; |
| 8 import '../elements/elements.dart'; | 8 import '../elements/elements.dart'; |
| 9 import '../js_backend/js_backend.dart'; | 9 import '../js_backend/js_backend.dart'; |
| 10 import '../types/types.dart'; | 10 import '../types/types.dart'; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 if (name == '>=') return const GreaterEqualSpecializer(); | 67 if (name == '>=') return const GreaterEqualSpecializer(); |
| 68 return const InvokeDynamicSpecializer(); | 68 return const InvokeDynamicSpecializer(); |
| 69 } | 69 } |
| 70 if (selector.isCall) { | 70 if (selector.isCall) { |
| 71 if (selector.namedArguments.length == 0) { | 71 if (selector.namedArguments.length == 0) { |
| 72 int argumentCount = selector.argumentCount; | 72 int argumentCount = selector.argumentCount; |
| 73 if (argumentCount == 0) { | 73 if (argumentCount == 0) { |
| 74 if (name == 'round') return const RoundSpecializer(); | 74 if (name == 'round') return const RoundSpecializer(); |
| 75 } else if (argumentCount == 1) { | 75 } else if (argumentCount == 1) { |
| 76 if (name == 'codeUnitAt') return const CodeUnitAtSpecializer(); | 76 if (name == 'codeUnitAt') return const CodeUnitAtSpecializer(); |
| 77 if (name == 'remainder') return const RemainderSpecializer(); |
| 77 } | 78 } |
| 78 } | 79 } |
| 79 } | 80 } |
| 80 return const InvokeDynamicSpecializer(); | 81 return const InvokeDynamicSpecializer(); |
| 81 } | 82 } |
| 82 } | 83 } |
| 83 | 84 |
| 84 class IndexAssignSpecializer extends InvokeDynamicSpecializer { | 85 class IndexAssignSpecializer extends InvokeDynamicSpecializer { |
| 85 const IndexAssignSpecializer(); | 86 const IndexAssignSpecializer(); |
| 86 | 87 |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); | 301 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
| 301 } | 302 } |
| 302 | 303 |
| 303 BinaryOperation operation(ConstantSystem constantSystem) { | 304 BinaryOperation operation(ConstantSystem constantSystem) { |
| 304 return constantSystem.modulo; | 305 return constantSystem.modulo; |
| 305 } | 306 } |
| 306 | 307 |
| 307 HInstruction newBuiltinVariant( | 308 HInstruction newBuiltinVariant( |
| 308 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { | 309 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 309 // Modulo cannot be mapped to the native operator (different semantics). | 310 // Modulo cannot be mapped to the native operator (different semantics). |
| 310 // TODO(sra): For non-negative values we can use JavaScript's %. | 311 |
| 312 // We can use HRemainder if both inputs are non-negative and the receiver |
| 313 // cannot be -0.0. Note that -0.0 is considered to be an int, so until we |
| 314 // track -0.0 precisely, we have to syntatically filter inputs that cannot |
| 315 // generate -0.0. |
| 316 bool canBePositiveZero(HInstruction input) { |
| 317 if (input is HConstant) { |
| 318 ConstantValue value = input.constant; |
| 319 if (value is DoubleConstantValue && value.isZero) return true; |
| 320 if (value is IntConstantValue && value.isZero) return true; |
| 321 return false; |
| 322 } |
| 323 return true; |
| 324 } |
| 325 |
| 326 bool inPhi = false; |
| 327 bool canBeNegativeZero(HInstruction input) { |
| 328 if (input is HConstant) { |
| 329 ConstantValue value = input.constant; |
| 330 if (value is DoubleConstantValue && value.isMinusZero) return true; |
| 331 return false; |
| 332 } |
| 333 if (input is HAdd) { |
| 334 // '+' can only generate -0.0 when both inputs are -0.0. |
| 335 return canBeNegativeZero(input.left) && canBeNegativeZero(input.right); |
| 336 } |
| 337 if (input is HSubtract) { |
| 338 return canBeNegativeZero(input.left) && canBePositiveZero(input.right); |
| 339 } |
| 340 if (input is HPhi) { |
| 341 if (inPhi) return true; |
| 342 inPhi = true; |
| 343 bool result = input.inputs.any(canBeNegativeZero); |
| 344 inPhi = false; |
| 345 return result; |
| 346 } |
| 347 return true; |
| 348 } |
| 349 |
| 350 if (inputsArePositiveIntegers(instruction, closedWorld) && |
| 351 !canBeNegativeZero(instruction.getDartReceiver(closedWorld))) { |
| 352 return new HRemainder( |
| 353 instruction.inputs[1], |
| 354 instruction.inputs[2], |
| 355 instruction.selector, |
| 356 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
| 357 } |
| 358 // TODO(sra): |
| 359 // a % N --> a & (N-1), N=2^k, where a>=0, does not have -0.0 problem. |
| 360 |
| 361 // TODO(sra): We could avoid problems with -0.0 if we generate x % y as (x + |
| 362 // 0) % y, but we would have to fix HAdd optimizations. |
| 363 |
| 364 // TODO(sra): We could replace $mod with HRemainder when we don't care about |
| 365 // a -0.0 result (e.g. a % 10 == 0, a[i % 3]). This is tricky, since we |
| 366 // don't want to ruin GVN opportunities. |
| 311 return null; | 367 return null; |
| 312 } | 368 } |
| 313 } | 369 } |
| 314 | 370 |
| 371 class RemainderSpecializer extends BinaryArithmeticSpecializer { |
| 372 const RemainderSpecializer(); |
| 373 |
| 374 TypeMask computeTypeFromInputTypes( |
| 375 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 376 if (inputsArePositiveIntegers(instruction, closedWorld)) { |
| 377 return closedWorld.commonMasks.positiveIntType; |
| 378 } |
| 379 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
| 380 } |
| 381 |
| 382 BinaryOperation operation(ConstantSystem constantSystem) { |
| 383 return constantSystem.remainder; |
| 384 } |
| 385 |
| 386 HInstruction newBuiltinVariant( |
| 387 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 388 JavaScriptBackend backend = compiler.backend; |
| 389 return new HRemainder( |
| 390 instruction.inputs[1], |
| 391 instruction.inputs[2], |
| 392 instruction.selector, |
| 393 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
| 394 } |
| 395 } |
| 396 |
| 315 class MultiplySpecializer extends BinaryArithmeticSpecializer { | 397 class MultiplySpecializer extends BinaryArithmeticSpecializer { |
| 316 const MultiplySpecializer(); | 398 const MultiplySpecializer(); |
| 317 | 399 |
| 318 BinaryOperation operation(ConstantSystem constantSystem) { | 400 BinaryOperation operation(ConstantSystem constantSystem) { |
| 319 return constantSystem.multiply; | 401 return constantSystem.multiply; |
| 320 } | 402 } |
| 321 | 403 |
| 322 TypeMask computeTypeFromInputTypes( | 404 TypeMask computeTypeFromInputTypes( |
| 323 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { | 405 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 324 if (inputsArePositiveIntegers(instruction, closedWorld)) { | 406 if (inputsArePositiveIntegers(instruction, closedWorld)) { |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 776 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { | 858 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 777 HInstruction receiver = instruction.getDartReceiver(closedWorld); | 859 HInstruction receiver = instruction.getDartReceiver(closedWorld); |
| 778 if (receiver.isNumberOrNull(closedWorld)) { | 860 if (receiver.isNumberOrNull(closedWorld)) { |
| 779 // Even if there is no builtin equivalent instruction, we know the | 861 // Even if there is no builtin equivalent instruction, we know the |
| 780 // instruction does not have any side effect, and that it can be GVN'ed. | 862 // instruction does not have any side effect, and that it can be GVN'ed. |
| 781 clearAllSideEffects(instruction); | 863 clearAllSideEffects(instruction); |
| 782 } | 864 } |
| 783 return null; | 865 return null; |
| 784 } | 866 } |
| 785 } | 867 } |
| OLD | NEW |