Chromium Code Reviews| Index: Source/wtf/SaturatedArithmetic.h |
| diff --git a/Source/wtf/SaturatedArithmetic.h b/Source/wtf/SaturatedArithmetic.h |
| index 981276f7c484fa779d5a30869670081984e0bfd8..fe3ff3c383dc8fdfc5a2b9900ae93ad44fd3cf5f 100644 |
| --- a/Source/wtf/SaturatedArithmetic.h |
| +++ b/Source/wtf/SaturatedArithmetic.h |
| @@ -31,19 +31,30 @@ |
| #ifndef SaturatedArithmetic_h |
| #define SaturatedArithmetic_h |
| +#include "wtf/CPU.h" |
| #include <limits> |
| #include <stdint.h> |
| +#if CPU(ARM_TRADITIONAL) && COMPILER(GCC) |
| + |
| +// If we're building ARM on GCC we replace the C++ versions with some |
| +// native arm assembly for speed. |
| +#include "wtf/asm/SaturatedArithmeticAsm.h" |
|
eseidel
2014/06/20 16:30:20
I probably would have called it wtf/SaturatedArith
picksi
2014/06/23 15:30:43
Done.
|
| + |
| +#else |
| + |
| ALWAYS_INLINE int32_t saturatedAddition(int32_t a, int32_t b) |
| { |
| uint32_t ua = a; |
| uint32_t ub = b; |
| uint32_t result = ua + ub; |
| - // Can only overflow if the signed bit of the two values match. If the signed |
| - // bit of the result and one of the values differ it did overflow. |
| - if (!((ua ^ ub) >> 31) & (result ^ ua) >> 31) |
| + // Can only overflow if the signed bit of the two values match. If the |
| + // signed bit of the result and one of the values differ it overflowed. |
| + |
| + if (~(ua ^ ub) & (result ^ ua) & (1 << 31)) { |
| result = std::numeric_limits<int>::max() + (ua >> 31); |
|
Stephen Chennney
2014/06/20 14:46:56
No braces and immediately "return std::num..."
picksi
2014/06/23 15:30:43
Done.
|
| + } |
| return result; |
| } |
| @@ -54,12 +65,60 @@ ALWAYS_INLINE int32_t saturatedSubtraction(int32_t a, int32_t b) |
| uint32_t ub = b; |
| uint32_t result = ua - ub; |
| - // Can only overflow if the signed bit of the two values do not match. If the |
| - // signed bit of the result and the first value differ it did overflow. |
| - if ((ua ^ ub) >> 31 & (result ^ ua) >> 31) |
| + // Can only overflow if the signed bit of the two input values differ. If |
| + // the signed bit of the result and the first value differ it overflowed. |
| + |
| + if ((ua ^ ub) & (result ^ ua) & (1 << 31)) { |
| result = std::numeric_limits<int>::max() + (ua >> 31); |
|
Stephen Chennney
2014/06/20 14:46:56
Ditto.
picksi
2014/06/23 15:30:43
Done.
|
| + } |
| return result; |
| } |
| +inline int getMaxSaturatedSetResultForTesting(int FractionalShift) |
| +{ |
| + // For C version the set function maxes out to max int, this differs from |
| + // the ARM asm version, see SaturatedArithmetiAsm.h for the equivlent asm |
| + // version. |
| + return std::numeric_limits<int>::max(); |
| +} |
| + |
| +inline int getMinSaturatedSetResultForTesting(int FractionalShift) |
| +{ |
| + return std::numeric_limits<int>::min(); |
| +} |
| + |
| +ALWAYS_INLINE int saturatedSet(int value, int FractionalShift) |
| +{ |
| + const int intMaxForLayoutUnit = |
| + std::numeric_limits<int>::max() >> FractionalShift; |
| + |
| + const int intMinForLayoutUnit = |
| + std::numeric_limits<int>::min() >> FractionalShift; |
| + |
| + if (value >= intMaxForLayoutUnit) { |
| + return std::numeric_limits<int>::max(); |
| + } |
|
Stephen Chennney
2014/06/20 14:46:56
No braces on single line statements in Blink.
picksi
2014/06/23 15:30:43
Done.
|
| + |
| + if (value <= intMinForLayoutUnit) { |
| + return std::numeric_limits<int>::min(); |
| + } |
|
Stephen Chennney
2014/06/20 14:46:56
Ditto.
picksi
2014/06/23 15:30:43
Done.
|
| + |
| + return value << FractionalShift; |
| +} |
| + |
| + |
| +ALWAYS_INLINE int saturatedSet(unsigned value, int FractionalShift) |
| +{ |
| + const unsigned intMaxForLayoutUnit = |
| + std::numeric_limits<int>::max() >> FractionalShift; |
| + |
| + if (value >= intMaxForLayoutUnit) { |
| + return std::numeric_limits<int>::max(); |
| + } |
|
Stephen Chennney
2014/06/20 14:46:56
Ditto,
picksi
2014/06/23 15:30:43
Done.
|
| + |
| + return value << FractionalShift; |
| +} |
| + |
| +#endif // CPU(ARM_TRADITIONAL) && COMPILER(GCC) |
| #endif // SaturatedArithmetic_h |