RFR: 8234331: Add robust and optimized utility for rounding up to next power of two+

Claes Redestad claes.redestad at oracle.com
Wed Dec 4 10:18:26 UTC 2019


On 2019-12-04 03:28, John Rose wrote:
> On Dec 3, 2019, at 3:38 PM, Claes Redestad <claes.redestad at oracle.com 
> <mailto:claes.redestad at oracle.com>> wrote:
>>
>> http://cr.openjdk.java.net/~redestad/8234331/open.03
> 
> Nice work!

Thanks!

> 
> A few minor complaints follow:
> 
> I’m not totally comfortable with the proliferation of tiny header files.
> Are we crashing from one extreme (globalDefinitions.hpp) toward the
> other (usefulZeroConstant.hpp)?  So having count_leading_zeros.hpp
> is arguably a correction, but then adding powerOfTwo.hpp feels like
> an over-correction.  To be followed by more over-corrections:
> count_trailing_zeroes.hpp, populationCount.hpp, and so on.
> 
> You won’t be surprised to hear that I think this would be excessive
> splitting, and that a lumpier outcome would feel better to me, as a
> successor to the chaos globalDefinitions.hpp.  I propose putting
> anything involving integral bitmask operations into intBitmasks.hpp,
> including today’s count_trailing_zeroes.hpp and all the new stuff
> that will be like it.  Start by renaming count_trailing_zeroes.hpp and
> rolling the new stuff into it.  I can wait for this, but I’m going to 
> grumble
> some more if we keep going down this road to TinyHeaderVille.

I hear microservices is all the rage these days. :-)

I can agree that one-header-per-logical-function would become excessive,
but I think organizing functions into more logical units needs to be 
done iteratively as patterns emerge.

> 
> This particular code :
> +    if (high != 0) {
> +      _BitScanReverse(&index, x);
> +    } else {
> +      _BitScanReverse(&index, x);
> +      index += 32;
> +    }
> 
> is clearly untested, since it’s wrong. The `index+=32` belongs on the other
> branch.  (Or is it me?) 

You're both right and wrong: yes, this block is untested (we don't have
32-bit Windows builds in our test system). And the code is/was wrong,
since the statement in the first branch should read:

_BitScanReverse(&index, high); // high, not x

However, the += 32 is in the right place: when the upper 32-bit word of
a 64-bit is non-zero, the number of leading zeros is in the [0-31] 
range, but if it's in the lower 32-bit word the number of leading zeros 
is in the [32-63] range. _BitScanReverse only operates on a 32-bit int.

> The root cause of this is the needless obfuscation
> of the `index ^= 31` and `index ^= 63`.  Really??  Just say `31 - index` and
> `63 - index`, and the arithmetic reasoning will take care of itself.

I agree this is a bit obscure (a habit I probably picked up from 
Hacker's Delight and other sources), and will go with 31u|63u - index.

> 
> In the new code, `assert(lz > …)` and `assert(lz < …)` statements are in an
> unpredictable relative order, making it harder to compare and contrast the
> four versions.  Suggest putting the < before the > case more regularly.

Fixed.

> 
> To `next_power_of_2` I suggest adding an assert that the increment
> will not overflow.  The asserts won't catch `next_power_of_2(max_jint)`,
> not for sure.

Yes, adding a check for the max value should be sufficient, since other
overflows are asserted against in round_up:

assert(value != std::numeric_limits<T>::max(), "Overflow");

Updating in place and rerunning gtests on all platforms.

Thanks!

/Claes
> 
> — John B. Twiddler
> 


More information about the hotspot-compiler-dev mailing list