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 #include "src/base/bits.h"
      6 
      7 #include <limits>
      8 
      9 #include "src/base/logging.h"
     10 #include "src/base/safe_math.h"
     11 
     12 namespace v8 {
     13 namespace base {
     14 namespace bits {
     15 
     16 uint32_t RoundUpToPowerOfTwo32(uint32_t value) {
     17   DCHECK_LE(value, uint32_t{1} << 31);
     18   if (value) --value;
     19 // Use computation based on leading zeros if we have compiler support for that.
     20 #if V8_HAS_BUILTIN_CLZ || V8_CC_MSVC
     21   return 1u << (32 - CountLeadingZeros(value));
     22 #else
     23   value |= value >> 1;
     24   value |= value >> 2;
     25   value |= value >> 4;
     26   value |= value >> 8;
     27   value |= value >> 16;
     28   return value + 1;
     29 #endif
     30 }
     31 
     32 uint64_t RoundUpToPowerOfTwo64(uint64_t value) {
     33   DCHECK_LE(value, uint64_t{1} << 63);
     34   if (value) --value;
     35 // Use computation based on leading zeros if we have compiler support for that.
     36 #if V8_HAS_BUILTIN_CLZ
     37   return uint64_t{1} << (64 - CountLeadingZeros(value));
     38 #else
     39   value |= value >> 1;
     40   value |= value >> 2;
     41   value |= value >> 4;
     42   value |= value >> 8;
     43   value |= value >> 16;
     44   value |= value >> 32;
     45   return value + 1;
     46 #endif
     47 }
     48 
     49 
     50 int32_t SignedMulHigh32(int32_t lhs, int32_t rhs) {
     51   int64_t const value = static_cast<int64_t>(lhs) * static_cast<int64_t>(rhs);
     52   return bit_cast<int32_t, uint32_t>(bit_cast<uint64_t>(value) >> 32u);
     53 }
     54 
     55 
     56 int32_t SignedMulHighAndAdd32(int32_t lhs, int32_t rhs, int32_t acc) {
     57   return bit_cast<int32_t>(bit_cast<uint32_t>(acc) +
     58                            bit_cast<uint32_t>(SignedMulHigh32(lhs, rhs)));
     59 }
     60 
     61 
     62 int32_t SignedDiv32(int32_t lhs, int32_t rhs) {
     63   if (rhs == 0) return 0;
     64   if (rhs == -1) return -lhs;
     65   return lhs / rhs;
     66 }
     67 
     68 
     69 int32_t SignedMod32(int32_t lhs, int32_t rhs) {
     70   if (rhs == 0 || rhs == -1) return 0;
     71   return lhs % rhs;
     72 }
     73 
     74 
     75 int64_t FromCheckedNumeric(const internal::CheckedNumeric<int64_t> value) {
     76   if (value.IsValid())
     77     return value.ValueUnsafe();
     78 
     79   // We could return max/min but we don't really expose what the maximum delta
     80   // is. Instead, return max/(-max), which is something that clients can reason
     81   // about.
     82   // TODO(rvargas) crbug.com/332611: don't use internal values.
     83   int64_t limit = std::numeric_limits<int64_t>::max();
     84   if (value.validity() == internal::RANGE_UNDERFLOW)
     85     limit = -limit;
     86   return value.ValueOrDefault(limit);
     87 }
     88 
     89 
     90 int64_t SignedSaturatedAdd64(int64_t lhs, int64_t rhs) {
     91   internal::CheckedNumeric<int64_t> rv(lhs);
     92   rv += rhs;
     93   return FromCheckedNumeric(rv);
     94 }
     95 
     96 
     97 int64_t SignedSaturatedSub64(int64_t lhs, int64_t rhs) {
     98   internal::CheckedNumeric<int64_t> rv(lhs);
     99   rv -= rhs;
    100   return FromCheckedNumeric(rv);
    101 }
    102 
    103 bool SignedMulOverflow32(int32_t lhs, int32_t rhs, int32_t* val) {
    104   internal::CheckedNumeric<int32_t> rv(lhs);
    105   rv *= rhs;
    106   int32_t limit = std::numeric_limits<int32_t>::max();
    107   *val = rv.ValueOrDefault(limit);
    108   return !rv.IsValid();
    109 }
    110 
    111 bool SignedMulOverflow64(int64_t lhs, int64_t rhs, int64_t* val) {
    112   internal::CheckedNumeric<int64_t> rv(lhs);
    113   rv *= rhs;
    114   int64_t limit = std::numeric_limits<int64_t>::max();
    115   *val = rv.ValueOrDefault(limit);
    116   return !rv.IsValid();
    117 }
    118 
    119 }  // namespace bits
    120 }  // namespace base
    121 }  // namespace v8
    122