8343700: ceil_log2 should not loop endlessly

Reviewed-by: shade, kbarrett, aph, stuefe
This commit is contained in:
Sonia Zaldana Calles 2024-11-19 19:13:09 +00:00
parent 6a5256ec04
commit 3328b4ecf2
3 changed files with 47 additions and 7 deletions

View File

@ -44,7 +44,7 @@ const size_t REHASH_LEN = 100;
Dictionary::Dictionary(ClassLoaderData* loader_data, size_t table_size)
: _number_of_entries(0), _loader_data(loader_data) {
size_t start_size_log_2 = MAX2(ceil_log2(table_size), (size_t)2); // 2 is minimum size even though some dictionaries only have one entry
size_t start_size_log_2 = MAX2(ceil_log2(table_size), 2); // 2 is minimum size even though some dictionaries only have one entry
size_t current_size = ((size_t)1) << start_size_log_2;
log_info(class, loader, data)("Dictionary start size: " SIZE_FORMAT " (" SIZE_FORMAT ")",
current_size, start_size_log_2);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -122,10 +122,9 @@ inline T next_power_of_2(T value) {
// Find log2 value greater than this input
template <typename T, ENABLE_IF(std::is_integral<T>::value)>
inline T ceil_log2(T value) {
T ret;
for (ret = 1; ((T)1 << ret) < value; ++ret);
return ret;
inline int ceil_log2(T value) {
assert(value > 0, "Invalid value");
return log2i_graceful(value - 1) + 1;
}
// Return the largest power of two that is a submultiple of the given value.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -305,3 +305,44 @@ TEST(power_of_2, log2i) {
check_log2i_variants_for((uint)0);
check_log2i_variants_for((jlong)0);
}
template <typename T> void test_ceil_log2() {
EXPECT_EQ(ceil_log2(T(1)), 0) << "value = " << T(1);
EXPECT_EQ(ceil_log2(T(2)), 1) << "value = " << T(2);
EXPECT_EQ(ceil_log2(T(3)), 2) << "value = " << T(3);
EXPECT_EQ(ceil_log2(T(4)), 2) << "value = " << T(4);
EXPECT_EQ(ceil_log2(T(5)), 3) << "value = " << T(5);
EXPECT_EQ(ceil_log2(T(6)), 3) << "value = " << T(6);
EXPECT_EQ(ceil_log2(T(7)), 3) << "value = " << T(7);
EXPECT_EQ(ceil_log2(T(8)), 3) << "value = " << T(8);
EXPECT_EQ(ceil_log2(T(9)), 4) << "value = " << T(9);
EXPECT_EQ(ceil_log2(T(10)), 4) << "value = " << T(10);
// Test max values
if (std::is_unsigned<T>::value) {
EXPECT_EQ(ceil_log2(std::numeric_limits<T>::max()),
(int)(sizeof(T) * 8)) << "value = " << std::numeric_limits<T>::max();
} else {
EXPECT_EQ(ceil_log2(std::numeric_limits<T>::max()),
(int)(sizeof(T) * 8 - 1)) << "value = " << std::numeric_limits<T>::max();
}
}
TEST(power_of_2, ceil_log2) {
test_ceil_log2<int8_t>();
test_ceil_log2<int16_t>();
test_ceil_log2<int32_t>();
test_ceil_log2<int64_t>();
test_ceil_log2<uint8_t>();
test_ceil_log2<uint16_t>();
test_ceil_log2<uint32_t>();
test_ceil_log2<uint64_t>();
}
#ifdef ASSERT
TEST_VM_ASSERT_MSG(power_of_2, ceil_log2_invalid,
".*Invalid value") {
ceil_log2(0);
}
#endif // ASSERT