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