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
RoundUpToPowerOfTwo32(uint32_t value)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
RoundUpToPowerOfTwo64(uint64_t value)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
SignedMulHigh32(int32_t lhs,int32_t rhs)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
SignedMulHighAndAdd32(int32_t lhs,int32_t rhs,int32_t acc)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
SignedDiv32(int32_t lhs,int32_t rhs)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
SignedMod32(int32_t lhs,int32_t rhs)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
FromCheckedNumeric(const internal::CheckedNumeric<int64_t> value)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
SignedSaturatedAdd64(int64_t lhs,int64_t rhs)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
SignedSaturatedSub64(int64_t lhs,int64_t rhs)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
SignedMulOverflow32(int32_t lhs,int32_t rhs,int32_t * val)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
SignedMulOverflow64(int64_t lhs,int64_t rhs,int64_t * val)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