Home | History | Annotate | Download | only in base
      1 // Copyright 2014 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_BASE_BITS_H_
      6 #define V8_BASE_BITS_H_
      7 
      8 #include <stdint.h>
      9 
     10 #include "src/base/base-export.h"
     11 #include "src/base/macros.h"
     12 #if V8_CC_MSVC
     13 #include <intrin.h>
     14 #endif
     15 #if V8_OS_WIN32
     16 #include "src/base/win32-headers.h"
     17 #endif
     18 
     19 namespace v8 {
     20 namespace base {
     21 
     22 namespace internal {
     23 template <typename T>
     24 class CheckedNumeric;
     25 }
     26 
     27 namespace bits {
     28 
     29 // CountPopulation32(value) returns the number of bits set in |value|.
     30 inline unsigned CountPopulation32(uint32_t value) {
     31 #if V8_HAS_BUILTIN_POPCOUNT
     32   return __builtin_popcount(value);
     33 #else
     34   value = ((value >> 1) & 0x55555555) + (value & 0x55555555);
     35   value = ((value >> 2) & 0x33333333) + (value & 0x33333333);
     36   value = ((value >> 4) & 0x0f0f0f0f) + (value & 0x0f0f0f0f);
     37   value = ((value >> 8) & 0x00ff00ff) + (value & 0x00ff00ff);
     38   value = ((value >> 16) & 0x0000ffff) + (value & 0x0000ffff);
     39   return static_cast<unsigned>(value);
     40 #endif
     41 }
     42 
     43 
     44 // CountPopulation64(value) returns the number of bits set in |value|.
     45 inline unsigned CountPopulation64(uint64_t value) {
     46 #if V8_HAS_BUILTIN_POPCOUNT
     47   return __builtin_popcountll(value);
     48 #else
     49   return CountPopulation32(static_cast<uint32_t>(value)) +
     50          CountPopulation32(static_cast<uint32_t>(value >> 32));
     51 #endif
     52 }
     53 
     54 
     55 // Overloaded versions of CountPopulation32/64.
     56 inline unsigned CountPopulation(uint32_t value) {
     57   return CountPopulation32(value);
     58 }
     59 
     60 
     61 inline unsigned CountPopulation(uint64_t value) {
     62   return CountPopulation64(value);
     63 }
     64 
     65 
     66 // CountLeadingZeros32(value) returns the number of zero bits following the most
     67 // significant 1 bit in |value| if |value| is non-zero, otherwise it returns 32.
     68 inline unsigned CountLeadingZeros32(uint32_t value) {
     69 #if V8_HAS_BUILTIN_CLZ
     70   return value ? __builtin_clz(value) : 32;
     71 #elif V8_CC_MSVC
     72   unsigned long result;  // NOLINT(runtime/int)
     73   if (!_BitScanReverse(&result, value)) return 32;
     74   return static_cast<unsigned>(31 - result);
     75 #else
     76   value = value | (value >> 1);
     77   value = value | (value >> 2);
     78   value = value | (value >> 4);
     79   value = value | (value >> 8);
     80   value = value | (value >> 16);
     81   return CountPopulation32(~value);
     82 #endif
     83 }
     84 
     85 
     86 // CountLeadingZeros64(value) returns the number of zero bits following the most
     87 // significant 1 bit in |value| if |value| is non-zero, otherwise it returns 64.
     88 inline unsigned CountLeadingZeros64(uint64_t value) {
     89 #if V8_HAS_BUILTIN_CLZ
     90   return value ? __builtin_clzll(value) : 64;
     91 #else
     92   value = value | (value >> 1);
     93   value = value | (value >> 2);
     94   value = value | (value >> 4);
     95   value = value | (value >> 8);
     96   value = value | (value >> 16);
     97   value = value | (value >> 32);
     98   return CountPopulation64(~value);
     99 #endif
    100 }
    101 
    102 
    103 // ReverseBits(value) returns |value| in reverse bit order.
    104 template <typename T>
    105 T ReverseBits(T value) {
    106   DCHECK((sizeof(value) == 1) || (sizeof(value) == 2) || (sizeof(value) == 4) ||
    107          (sizeof(value) == 8));
    108   T result = 0;
    109   for (unsigned i = 0; i < (sizeof(value) * 8); i++) {
    110     result = (result << 1) | (value & 1);
    111     value >>= 1;
    112   }
    113   return result;
    114 }
    115 
    116 // CountTrailingZeros32(value) returns the number of zero bits preceding the
    117 // least significant 1 bit in |value| if |value| is non-zero, otherwise it
    118 // returns 32.
    119 inline unsigned CountTrailingZeros32(uint32_t value) {
    120 #if V8_HAS_BUILTIN_CTZ
    121   return value ? __builtin_ctz(value) : 32;
    122 #elif V8_CC_MSVC
    123   unsigned long result;  // NOLINT(runtime/int)
    124   if (!_BitScanForward(&result, value)) return 32;
    125   return static_cast<unsigned>(result);
    126 #else
    127   if (value == 0) return 32;
    128   unsigned count = 0;
    129   for (value ^= value - 1; value >>= 1; ++count) {
    130   }
    131   return count;
    132 #endif
    133 }
    134 
    135 
    136 // CountTrailingZeros64(value) returns the number of zero bits preceding the
    137 // least significant 1 bit in |value| if |value| is non-zero, otherwise it
    138 // returns 64.
    139 inline unsigned CountTrailingZeros64(uint64_t value) {
    140 #if V8_HAS_BUILTIN_CTZ
    141   return value ? __builtin_ctzll(value) : 64;
    142 #else
    143   if (value == 0) return 64;
    144   unsigned count = 0;
    145   for (value ^= value - 1; value >>= 1; ++count) {
    146   }
    147   return count;
    148 #endif
    149 }
    150 
    151 // Overloaded versions of CountTrailingZeros32/64.
    152 inline unsigned CountTrailingZeros(uint32_t value) {
    153   return CountTrailingZeros32(value);
    154 }
    155 
    156 inline unsigned CountTrailingZeros(uint64_t value) {
    157   return CountTrailingZeros64(value);
    158 }
    159 
    160 // Returns true iff |value| is a power of 2.
    161 inline bool IsPowerOfTwo32(uint32_t value) {
    162   return value && !(value & (value - 1));
    163 }
    164 
    165 
    166 // Returns true iff |value| is a power of 2.
    167 inline bool IsPowerOfTwo64(uint64_t value) {
    168   return value && !(value & (value - 1));
    169 }
    170 
    171 
    172 // RoundUpToPowerOfTwo32(value) returns the smallest power of two which is
    173 // greater than or equal to |value|. If you pass in a |value| that is already a
    174 // power of two, it is returned as is. |value| must be less than or equal to
    175 // 0x80000000u. Implementation is from "Hacker's Delight" by Henry S. Warren,
    176 // Jr., figure 3-3, page 48, where the function is called clp2.
    177 V8_BASE_EXPORT uint32_t RoundUpToPowerOfTwo32(uint32_t value);
    178 
    179 // RoundDownToPowerOfTwo32(value) returns the greatest power of two which is
    180 // less than or equal to |value|. If you pass in a |value| that is already a
    181 // power of two, it is returned as is.
    182 inline uint32_t RoundDownToPowerOfTwo32(uint32_t value) {
    183   if (value > 0x80000000u) return 0x80000000u;
    184   uint32_t result = RoundUpToPowerOfTwo32(value);
    185   if (result > value) result >>= 1;
    186   return result;
    187 }
    188 
    189 
    190 // Precondition: 0 <= shift < 32
    191 inline uint32_t RotateRight32(uint32_t value, uint32_t shift) {
    192   if (shift == 0) return value;
    193   return (value >> shift) | (value << (32 - shift));
    194 }
    195 
    196 // Precondition: 0 <= shift < 32
    197 inline uint32_t RotateLeft32(uint32_t value, uint32_t shift) {
    198   if (shift == 0) return value;
    199   return (value << shift) | (value >> (32 - shift));
    200 }
    201 
    202 // Precondition: 0 <= shift < 64
    203 inline uint64_t RotateRight64(uint64_t value, uint64_t shift) {
    204   if (shift == 0) return value;
    205   return (value >> shift) | (value << (64 - shift));
    206 }
    207 
    208 // Precondition: 0 <= shift < 64
    209 inline uint64_t RotateLeft64(uint64_t value, uint64_t shift) {
    210   if (shift == 0) return value;
    211   return (value << shift) | (value >> (64 - shift));
    212 }
    213 
    214 
    215 // SignedAddOverflow32(lhs,rhs,val) performs a signed summation of |lhs| and
    216 // |rhs| and stores the result into the variable pointed to by |val| and
    217 // returns true if the signed summation resulted in an overflow.
    218 inline bool SignedAddOverflow32(int32_t lhs, int32_t rhs, int32_t* val) {
    219 #if V8_HAS_BUILTIN_SADD_OVERFLOW
    220   return __builtin_sadd_overflow(lhs, rhs, val);
    221 #else
    222   uint32_t res = static_cast<uint32_t>(lhs) + static_cast<uint32_t>(rhs);
    223   *val = bit_cast<int32_t>(res);
    224   return ((res ^ lhs) & (res ^ rhs) & (1U << 31)) != 0;
    225 #endif
    226 }
    227 
    228 
    229 // SignedSubOverflow32(lhs,rhs,val) performs a signed subtraction of |lhs| and
    230 // |rhs| and stores the result into the variable pointed to by |val| and
    231 // returns true if the signed subtraction resulted in an overflow.
    232 inline bool SignedSubOverflow32(int32_t lhs, int32_t rhs, int32_t* val) {
    233 #if V8_HAS_BUILTIN_SSUB_OVERFLOW
    234   return __builtin_ssub_overflow(lhs, rhs, val);
    235 #else
    236   uint32_t res = static_cast<uint32_t>(lhs) - static_cast<uint32_t>(rhs);
    237   *val = bit_cast<int32_t>(res);
    238   return ((res ^ lhs) & (res ^ ~rhs) & (1U << 31)) != 0;
    239 #endif
    240 }
    241 
    242 // SignedMulOverflow32(lhs,rhs,val) performs a signed multiplication of |lhs|
    243 // and |rhs| and stores the result into the variable pointed to by |val| and
    244 // returns true if the signed multiplication resulted in an overflow.
    245 V8_BASE_EXPORT bool SignedMulOverflow32(int32_t lhs, int32_t rhs, int32_t* val);
    246 
    247 // SignedAddOverflow64(lhs,rhs,val) performs a signed summation of |lhs| and
    248 // |rhs| and stores the result into the variable pointed to by |val| and
    249 // returns true if the signed summation resulted in an overflow.
    250 inline bool SignedAddOverflow64(int64_t lhs, int64_t rhs, int64_t* val) {
    251   uint64_t res = static_cast<uint64_t>(lhs) + static_cast<uint64_t>(rhs);
    252   *val = bit_cast<int64_t>(res);
    253   return ((res ^ lhs) & (res ^ rhs) & (1ULL << 63)) != 0;
    254 }
    255 
    256 
    257 // SignedSubOverflow64(lhs,rhs,val) performs a signed subtraction of |lhs| and
    258 // |rhs| and stores the result into the variable pointed to by |val| and
    259 // returns true if the signed subtraction resulted in an overflow.
    260 inline bool SignedSubOverflow64(int64_t lhs, int64_t rhs, int64_t* val) {
    261   uint64_t res = static_cast<uint64_t>(lhs) - static_cast<uint64_t>(rhs);
    262   *val = bit_cast<int64_t>(res);
    263   return ((res ^ lhs) & (res ^ ~rhs) & (1ULL << 63)) != 0;
    264 }
    265 
    266 // SignedMulOverflow64(lhs,rhs,val) performs a signed multiplication of |lhs|
    267 // and |rhs| and stores the result into the variable pointed to by |val| and
    268 // returns true if the signed multiplication resulted in an overflow.
    269 V8_BASE_EXPORT bool SignedMulOverflow64(int64_t lhs, int64_t rhs, int64_t* val);
    270 
    271 // SignedMulHigh32(lhs, rhs) multiplies two signed 32-bit values |lhs| and
    272 // |rhs|, extracts the most significant 32 bits of the result, and returns
    273 // those.
    274 V8_BASE_EXPORT int32_t SignedMulHigh32(int32_t lhs, int32_t rhs);
    275 
    276 // SignedMulHighAndAdd32(lhs, rhs, acc) multiplies two signed 32-bit values
    277 // |lhs| and |rhs|, extracts the most significant 32 bits of the result, and
    278 // adds the accumulate value |acc|.
    279 V8_BASE_EXPORT int32_t SignedMulHighAndAdd32(int32_t lhs, int32_t rhs,
    280                                              int32_t acc);
    281 
    282 // SignedDiv32(lhs, rhs) divides |lhs| by |rhs| and returns the quotient
    283 // truncated to int32. If |rhs| is zero, then zero is returned. If |lhs|
    284 // is minint and |rhs| is -1, it returns minint.
    285 V8_BASE_EXPORT int32_t SignedDiv32(int32_t lhs, int32_t rhs);
    286 
    287 // SignedMod32(lhs, rhs) divides |lhs| by |rhs| and returns the remainder
    288 // truncated to int32. If either |rhs| is zero or |lhs| is minint and |rhs|
    289 // is -1, it returns zero.
    290 V8_BASE_EXPORT int32_t SignedMod32(int32_t lhs, int32_t rhs);
    291 
    292 // UnsignedAddOverflow32(lhs,rhs,val) performs an unsigned summation of |lhs|
    293 // and |rhs| and stores the result into the variable pointed to by |val| and
    294 // returns true if the unsigned summation resulted in an overflow.
    295 inline bool UnsignedAddOverflow32(uint32_t lhs, uint32_t rhs, uint32_t* val) {
    296 #if V8_HAS_BUILTIN_SADD_OVERFLOW
    297   return __builtin_uadd_overflow(lhs, rhs, val);
    298 #else
    299   *val = lhs + rhs;
    300   return *val < (lhs | rhs);
    301 #endif
    302 }
    303 
    304 
    305 // UnsignedDiv32(lhs, rhs) divides |lhs| by |rhs| and returns the quotient
    306 // truncated to uint32. If |rhs| is zero, then zero is returned.
    307 inline uint32_t UnsignedDiv32(uint32_t lhs, uint32_t rhs) {
    308   return rhs ? lhs / rhs : 0u;
    309 }
    310 
    311 
    312 // UnsignedMod32(lhs, rhs) divides |lhs| by |rhs| and returns the remainder
    313 // truncated to uint32. If |rhs| is zero, then zero is returned.
    314 inline uint32_t UnsignedMod32(uint32_t lhs, uint32_t rhs) {
    315   return rhs ? lhs % rhs : 0u;
    316 }
    317 
    318 
    319 // Clamp |value| on overflow and underflow conditions.
    320 V8_BASE_EXPORT int64_t
    321 FromCheckedNumeric(const internal::CheckedNumeric<int64_t> value);
    322 
    323 // SignedSaturatedAdd64(lhs, rhs) adds |lhs| and |rhs|,
    324 // checks and returns the result.
    325 V8_BASE_EXPORT int64_t SignedSaturatedAdd64(int64_t lhs, int64_t rhs);
    326 
    327 // SignedSaturatedSub64(lhs, rhs) substracts |lhs| by |rhs|,
    328 // checks and returns the result.
    329 V8_BASE_EXPORT int64_t SignedSaturatedSub64(int64_t lhs, int64_t rhs);
    330 
    331 }  // namespace bits
    332 }  // namespace base
    333 }  // namespace v8
    334 
    335 #endif  // V8_BASE_BITS_H_
    336