Reland "[base] Introduce RoundUpToPowerOfTwo64"
With fix for architectures where x<<32 != x. Original change's description: > [base] Introduce RoundUpToPowerOfTwo64 > > And fix RoundUpToPowerOfTwo32 to return 1 for the input 0. > 0 is no power of two. > Beside being the correct value, this also avoids a special case in the > (new) fast path using the number of leading zeros. > > R=jochen@chromium.org, ahaas@chromium.org > > Change-Id: I87173495e13b334954bcebbb55724fb666dfa809 > Reviewed-on: https://chromium-review.googlesource.com/488143 > Reviewed-by: Jochen Eisinger <jochen@chromium.org> > Reviewed-by: Andreas Haas <ahaas@chromium.org> > Commit-Queue: Clemens Hammacher <clemensh@chromium.org> > Cr-Commit-Position: refs/heads/master@{#44925} TBR=ahaas@chromium.org,jochen@chromium.org,clemensh@chromium.org,v8-reviews@googlegroups.com Change-Id: I7b4719d84a419bb7b38e3b5c9d6d183275087ace Reviewed-on: https://chromium-review.googlesource.com/488981 Commit-Queue: Clemens Hammacher <clemensh@chromium.org> Reviewed-by: Clemens Hammacher <clemensh@chromium.org> Cr-Commit-Position: refs/heads/master@{#44951}
This commit is contained in:
parent
b3887f8a2c
commit
a32cd1c710
@ -14,14 +14,36 @@ namespace base {
|
||||
namespace bits {
|
||||
|
||||
uint32_t RoundUpToPowerOfTwo32(uint32_t value) {
|
||||
DCHECK_LE(value, 0x80000000u);
|
||||
value = value - 1;
|
||||
value = value | (value >> 1);
|
||||
value = value | (value >> 2);
|
||||
value = value | (value >> 4);
|
||||
value = value | (value >> 8);
|
||||
value = value | (value >> 16);
|
||||
DCHECK_LE(value, uint32_t{1} << 31);
|
||||
if (value) --value;
|
||||
// Use computation based on leading zeros if we have compiler support for that.
|
||||
#if V8_HAS_BUILTIN_CLZ || V8_CC_MSVC
|
||||
return 1u << (32 - CountLeadingZeros32(value));
|
||||
#else
|
||||
value |= value >> 1;
|
||||
value |= value >> 2;
|
||||
value |= value >> 4;
|
||||
value |= value >> 8;
|
||||
value |= value >> 16;
|
||||
return value + 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t RoundUpToPowerOfTwo64(uint64_t value) {
|
||||
DCHECK_LE(value, uint64_t{1} << 63);
|
||||
if (value) --value;
|
||||
// Use computation based on leading zeros if we have compiler support for that.
|
||||
#if V8_HAS_BUILTIN_CLZ
|
||||
return uint64_t{1} << (64 - CountLeadingZeros64(value));
|
||||
#else
|
||||
value |= value >> 1;
|
||||
value |= value >> 2;
|
||||
value |= value >> 4;
|
||||
value |= value >> 8;
|
||||
value |= value >> 16;
|
||||
value |= value >> 32;
|
||||
return value + 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -168,13 +168,15 @@ inline bool IsPowerOfTwo64(uint64_t value) {
|
||||
return value && !(value & (value - 1));
|
||||
}
|
||||
|
||||
|
||||
// RoundUpToPowerOfTwo32(value) returns the smallest power of two which is
|
||||
// greater than or equal to |value|. If you pass in a |value| that is already a
|
||||
// power of two, it is returned as is. |value| must be less than or equal to
|
||||
// 0x80000000u. Implementation is from "Hacker's Delight" by Henry S. Warren,
|
||||
// Jr., figure 3-3, page 48, where the function is called clp2.
|
||||
// 0x80000000u. Uses computation based on leading zeros if we have compiler
|
||||
// support for that. Falls back to the implementation from "Hacker's Delight" by
|
||||
// Henry S. Warren, Jr., figure 3-3, page 48, where the function is called clp2.
|
||||
V8_BASE_EXPORT uint32_t RoundUpToPowerOfTwo32(uint32_t value);
|
||||
// Same for 64 bit integers. |value| must be <= 2^63
|
||||
V8_BASE_EXPORT uint64_t RoundUpToPowerOfTwo64(uint64_t value);
|
||||
|
||||
// RoundDownToPowerOfTwo32(value) returns the greatest power of two which is
|
||||
// less than or equal to |value|. If you pass in a |value| that is already a
|
||||
|
@ -2083,11 +2083,9 @@ class ThreadImpl {
|
||||
void EnsureStackSpace(size_t size) {
|
||||
if (V8_LIKELY(static_cast<size_t>(stack_limit_ - sp_) >= size)) return;
|
||||
size_t old_size = stack_limit_ - stack_start_;
|
||||
size_t new_size = Max(size_t{8}, 2 * old_size);
|
||||
while (new_size < (sp_ - stack_start_) + size) {
|
||||
DCHECK_GE(std::numeric_limits<decltype(new_size)>::max() / 4, new_size);
|
||||
new_size *= 2;
|
||||
}
|
||||
size_t requested_size =
|
||||
base::bits::RoundUpToPowerOfTwo64((sp_ - stack_start_) + size);
|
||||
size_t new_size = Max(size_t{8}, Max(2 * old_size, requested_size));
|
||||
WasmVal* new_stack = zone_->NewArray<WasmVal>(new_size);
|
||||
memcpy(new_stack, stack_start_, old_size * sizeof(*sp_));
|
||||
sp_ = new_stack + (sp_ - stack_start_);
|
||||
|
@ -117,7 +117,8 @@ TEST(Bits, RoundUpToPowerOfTwo32) {
|
||||
TRACED_FORRANGE(uint32_t, shift, 0, 31) {
|
||||
EXPECT_EQ(1u << shift, RoundUpToPowerOfTwo32(1u << shift));
|
||||
}
|
||||
EXPECT_EQ(0u, RoundUpToPowerOfTwo32(0));
|
||||
EXPECT_EQ(1u, RoundUpToPowerOfTwo32(0));
|
||||
EXPECT_EQ(1u, RoundUpToPowerOfTwo32(1));
|
||||
EXPECT_EQ(4u, RoundUpToPowerOfTwo32(3));
|
||||
EXPECT_EQ(0x80000000u, RoundUpToPowerOfTwo32(0x7fffffffu));
|
||||
}
|
||||
@ -125,7 +126,24 @@ TEST(Bits, RoundUpToPowerOfTwo32) {
|
||||
|
||||
TEST(BitsDeathTest, DISABLE_IN_RELEASE(RoundUpToPowerOfTwo32)) {
|
||||
ASSERT_DEATH_IF_SUPPORTED({ RoundUpToPowerOfTwo32(0x80000001u); },
|
||||
"0x80000000");
|
||||
"Check failed:.* << 31");
|
||||
}
|
||||
|
||||
TEST(Bits, RoundUpToPowerOfTwo64) {
|
||||
TRACED_FORRANGE(uint64_t, shift, 0, 63) {
|
||||
uint64_t value = uint64_t{1} << shift;
|
||||
EXPECT_EQ(value, RoundUpToPowerOfTwo64(value));
|
||||
}
|
||||
EXPECT_EQ(uint64_t{1}, RoundUpToPowerOfTwo64(0));
|
||||
EXPECT_EQ(uint64_t{1}, RoundUpToPowerOfTwo64(1));
|
||||
EXPECT_EQ(uint64_t{4}, RoundUpToPowerOfTwo64(3));
|
||||
EXPECT_EQ(uint64_t{1} << 63, RoundUpToPowerOfTwo64((uint64_t{1} << 63) - 1));
|
||||
EXPECT_EQ(uint64_t{1} << 63, RoundUpToPowerOfTwo64(uint64_t{1} << 63));
|
||||
}
|
||||
|
||||
TEST(BitsDeathTest, DISABLE_IN_RELEASE(RoundUpToPowerOfTwo64)) {
|
||||
ASSERT_DEATH_IF_SUPPORTED({ RoundUpToPowerOfTwo64((uint64_t{1} << 63) + 1); },
|
||||
"Check failed:.* << 63");
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user