Index: sdk/lib/_internal/lib/js_number.dart |
=================================================================== |
--- sdk/lib/_internal/lib/js_number.dart (revision 31017) |
+++ sdk/lib/_internal/lib/js_number.dart (working copy) |
@@ -201,14 +201,21 @@ |
bool _isInt32(value) => JS('bool', '(# | 0) === #', value, value); |
num operator ~/(num other) { |
+ if (false) _tdivFast(other); // Ensure resolution. |
if (_isInt32(this) && _isInt32(other) && 0 != other && -1 != other) { |
return JS('num', r'(# / #) | 0', this, other); |
} else { |
- return _slowTdiv(other); |
+ return _tdivSlow(other); |
} |
} |
- num _slowTdiv(num other) { |
+ num _tdivFast(num other) { |
+ return _isInt32(this) |
+ ? JS('num', r'(# / #) | 0', this, other) |
+ : (JS('num', r'# / #', this, other)).toInt(); |
+ } |
+ |
+ num _tdivSlow(num other) { |
if (other is !num) throw new ArgumentError(other); |
return (JS('num', r'# / #', this, other)).toInt(); |
} |
@@ -221,32 +228,51 @@ |
num operator <<(num other) { |
if (other is !num) throw new ArgumentError(other); |
if (JS('num', '#', other) < 0) throw new ArgumentError(other); |
+ return _shlPositive(other); |
+ } |
+ |
+ num _shlPositive(num other) { |
// JavaScript only looks at the last 5 bits of the shift-amount. Shifting |
// by 33 is hence equivalent to a shift by 1. |
- if (JS('bool', r'# > 31', other)) return 0; |
- return JS('JSUInt32', r'(# << #) >>> 0', this, other); |
+ return JS('bool', r'# > 31', other) |
+ ? 0 |
+ : JS('JSUInt32', r'(# << #) >>> 0', this, other); |
} |
num operator >>(num other) { |
+ if (false) _shrReceiverPositive(other); |
if (other is !num) throw new ArgumentError(other); |
if (JS('num', '#', other) < 0) throw new ArgumentError(other); |
- if (JS('num', '#', this) > 0) { |
- // JavaScript only looks at the last 5 bits of the shift-amount. In JS |
- // shifting by 33 is hence equivalent to a shift by 1. Shortcut the |
- // computation when that happens. |
- if (JS('bool', r'# > 31', other)) return 0; |
- // Given that 'a' is positive we must not use '>>'. Otherwise a number |
- // that has the 31st bit set would be treated as negative and shift in |
- // ones. |
- return JS('JSUInt32', r'# >>> #', this, other); |
- } |
- // For negative numbers we just clamp the shift-by amount. 'a' could be |
- // negative but not have its 31st bit set. The ">>" would then shift in |
- // 0s instead of 1s. Therefore we cannot simply return 0xFFFFFFFF. |
- if (JS('num', '#', other) > 31) other = 31; |
- return JS('JSUInt32', r'(# >> #) >>> 0', this, other); |
+ return _shrOtherPositive(other); |
} |
+ num _shrOtherPositive(num other) { |
+ return JS('num', '#', this) > 0 |
+ ? _shrBothPositive(other) |
+ // For negative numbers we just clamp the shift-by amount. |
+ // `this` could be negative but not have its 31st bit set. |
+ // The ">>" would then shift in 0s instead of 1s. Therefore |
+ // we cannot simply return 0xFFFFFFFF. |
+ : JS('JSUInt32', r'(# >> #) >>> 0', this, other > 31 ? 31 : other); |
+ } |
+ |
+ num _shrReceiverPositive(num other) { |
+ if (JS('num', '#', other) < 0) throw new ArgumentError(other); |
+ return _shrBothPositive(other); |
+ } |
+ |
+ num _shrBothPositive(num other) { |
+ return JS('bool', r'# > 31', other) |
+ // JavaScript only looks at the last 5 bits of the shift-amount. In JS |
+ // shifting by 33 is hence equivalent to a shift by 1. Shortcut the |
+ // computation when that happens. |
+ ? 0 |
+ // Given that `this` is positive we must not use '>>'. Otherwise a |
+ // number that has the 31st bit set would be treated as negative and |
+ // shift in ones. |
+ : JS('JSUInt32', r'# >>> #', this, other); |
+ } |
+ |
num operator &(num other) { |
if (other is !num) throw new ArgumentError(other); |
return JS('JSUInt32', r'(# & #) >>> 0', this, other); |