Chromium Code Reviews| 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 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 299 return super.computeTypeFromInputTypes(instruction, compiler); | 300 return super.computeTypeFromInputTypes(instruction, compiler); |
| 300 } | 301 } |
| 301 | 302 |
| 302 BinaryOperation operation(ConstantSystem constantSystem) { | 303 BinaryOperation operation(ConstantSystem constantSystem) { |
| 303 return constantSystem.modulo; | 304 return constantSystem.modulo; |
| 304 } | 305 } |
| 305 | 306 |
| 306 HInstruction newBuiltinVariant( | 307 HInstruction newBuiltinVariant( |
| 307 HInvokeDynamic instruction, Compiler compiler) { | 308 HInvokeDynamic instruction, Compiler compiler) { |
| 308 // Modulo cannot be mapped to the native operator (different semantics). | 309 // Modulo cannot be mapped to the native operator (different semantics). |
| 309 // TODO(sra): For non-negative values we can use JavaScript's %. | 310 |
| 311 // We can use HRemainder if both inputs are non-negative and the receiver | |
| 312 // cannot be -0.0. Note that -0.0 is considered to be an int, so until we | |
| 313 // track -0.0 precisely, we have to syntatically filter inputs that cannot | |
| 314 // generate -0.0. | |
| 315 bool canBePositiveZero(HInstruction input) { | |
| 316 if (input is HConstant) { | |
| 317 ConstantValue value = input.constant; | |
| 318 if (value is DoubleConstantValue && value.isZero) return true; | |
| 319 if (value is IntConstantValue && value.isZero) return true; | |
| 320 return false; | |
| 321 } | |
| 322 return true; | |
| 323 } | |
| 324 bool inPhi = false; | |
| 325 bool canBeNegativeZero(HInstruction input) { | |
| 326 if (input is HConstant) { | |
| 327 ConstantValue value = input.constant; | |
| 328 if (value is DoubleConstantValue && value.isMinusZero) return true; | |
| 329 return false; | |
| 330 } | |
| 331 if (input is HAdd) { | |
| 332 // '+' is can only generate -0.0 when both inputs are -0.0. | |
|
Siggi Cherem (dart-lang)
2016/12/08 14:54:29
is can => can
sra1
2016/12/08 20:43:44
Done.
| |
| 333 return canBeNegativeZero(input.left) && canBeNegativeZero(input.right); | |
| 334 } | |
| 335 if (input is HSubtract) { | |
| 336 return canBeNegativeZero(input.left) && canBePositiveZero(input.right); | |
| 337 } | |
| 338 if (input is HPhi) { | |
| 339 if (inPhi) return true; | |
| 340 inPhi = true; | |
| 341 bool result = input.inputs.any(canBeNegativeZero); | |
| 342 inPhi = false; | |
| 343 return result; | |
| 344 } | |
| 345 return true; | |
| 346 } | |
| 347 | |
| 348 if (inputsArePositiveIntegers(instruction, compiler) && | |
| 349 !canBeNegativeZero(instruction.getDartReceiver(compiler))) { | |
| 350 return new HRemainder( | |
| 351 instruction.inputs[1], | |
| 352 instruction.inputs[2], | |
| 353 instruction.selector, | |
| 354 computeTypeFromInputTypes(instruction, compiler)); | |
| 355 } | |
| 356 // TODO(sra): | |
| 357 // a % N --> a & (N-1), N=2^k, where a>=0, does not have -0.0 problem. | |
| 358 | |
| 359 // TODO(sra): We could avoid problems with -0.0 if we generate x % y as (x + | |
| 360 // 0) % y, but we would have to fix HAdd optimizations. | |
| 361 | |
| 362 // TODO(sra): We could replace $mod with HRemainder when we don't care about | |
| 363 // a -0.0 result (e.g. a % 10 == 0, a[i % 3]). This is tricky, since we | |
| 364 // don't want to ruin GVN opportunities. | |
| 310 return null; | 365 return null; |
| 311 } | 366 } |
| 312 } | 367 } |
| 313 | 368 |
| 369 class RemainderSpecializer extends BinaryArithmeticSpecializer { | |
| 370 const RemainderSpecializer(); | |
| 371 | |
| 372 TypeMask computeTypeFromInputTypes( | |
| 373 HInvokeDynamic instruction, Compiler compiler) { | |
| 374 if (inputsArePositiveIntegers(instruction, compiler)) { | |
| 375 JavaScriptBackend backend = compiler.backend; | |
| 376 return backend.positiveIntType; | |
| 377 } | |
| 378 return super.computeTypeFromInputTypes(instruction, compiler); | |
| 379 } | |
| 380 | |
| 381 BinaryOperation operation(ConstantSystem constantSystem) { | |
| 382 return constantSystem.remainder; | |
| 383 } | |
| 384 | |
| 385 HInstruction newBuiltinVariant( | |
| 386 HInvokeDynamic instruction, Compiler compiler) { | |
| 387 JavaScriptBackend backend = compiler.backend; | |
| 388 return new HRemainder(instruction.inputs[1], instruction.inputs[2], | |
| 389 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | |
| 390 } | |
| 391 } | |
| 392 | |
| 314 class MultiplySpecializer extends BinaryArithmeticSpecializer { | 393 class MultiplySpecializer extends BinaryArithmeticSpecializer { |
| 315 const MultiplySpecializer(); | 394 const MultiplySpecializer(); |
| 316 | 395 |
| 317 BinaryOperation operation(ConstantSystem constantSystem) { | 396 BinaryOperation operation(ConstantSystem constantSystem) { |
| 318 return constantSystem.multiply; | 397 return constantSystem.multiply; |
| 319 } | 398 } |
| 320 | 399 |
| 321 TypeMask computeTypeFromInputTypes( | 400 TypeMask computeTypeFromInputTypes( |
| 322 HInvokeDynamic instruction, Compiler compiler) { | 401 HInvokeDynamic instruction, Compiler compiler) { |
| 323 if (inputsArePositiveIntegers(instruction, compiler)) { | 402 if (inputsArePositiveIntegers(instruction, compiler)) { |
| (...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 763 HInvokeDynamic instruction, Compiler compiler) { | 842 HInvokeDynamic instruction, Compiler compiler) { |
| 764 HInstruction receiver = instruction.getDartReceiver(compiler); | 843 HInstruction receiver = instruction.getDartReceiver(compiler); |
| 765 if (receiver.isNumberOrNull(compiler)) { | 844 if (receiver.isNumberOrNull(compiler)) { |
| 766 // Even if there is no builtin equivalent instruction, we know the | 845 // Even if there is no builtin equivalent instruction, we know the |
| 767 // instruction does not have any side effect, and that it can be GVN'ed. | 846 // instruction does not have any side effect, and that it can be GVN'ed. |
| 768 clearAllSideEffects(instruction); | 847 clearAllSideEffects(instruction); |
| 769 } | 848 } |
| 770 return null; | 849 return null; |
| 771 } | 850 } |
| 772 } | 851 } |
| OLD | NEW |