RFR: 8346836: C2: Introduce a way to verify the correctness of ConstraintCastNodes at runtime [v5]

Vladimir Ivanov vlivanov at openjdk.org
Fri Feb 7 17:25:22 UTC 2025


On Thu, 6 Feb 2025 19:17:03 GMT, Quan Anh Mai <qamai at openjdk.org> wrote:

>> Hi,
>> 
>> This patch adds a develop flag `VerifyConstraintCasts`, which will verify the correctness of `CastIINode`s and `CastLLNode`s at runtime and crash the VM if the dynamic value lies outside the type value range.
>> 
>> Please take a look, thanks a lot.
>
> Quan Anh Mai has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains seven additional commits since the last revision:
> 
>  - Merge branch 'master' into verifycast
>  - better comments
>  - move test to a new file, add block_comment
>  - add tests
>  - make VerifyConstraintCast uint, better debug info
>  - Merge branch 'master' into verifycast
>  - Introduce VerifyConstraintCasts

Very nice!

src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp line 840:

> 838: 
> 839: #ifdef ASSERT
> 840: void C2_MacroAssembler::checked_cast_int(const TypeInt* type, Register dst) {

Naming is a bit confusing here. It is a register which holds the value being range checked, not a register where new value is put.

src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp line 844:

> 842:   Label fail;
> 843:   Label succeed;
> 844:   cmpl(dst, type->_lo);

Optimization idea: some range checks may be redundant (when `lo`/`hi` hold min/max values).

src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp line 852:

> 850:   movl(rcx, type->_lo);
> 851:   movl(rdx, type->_hi);
> 852:   hlt(); // hlt so we have the stack trace

That's interesting. Sounds like a problem in `NativeStackPrinter::print_stack()`.

Speaking of debugging output, a call into a local helper function (encapsulating pretty printing logic) followed by a hlt call will do the job. But, considering the usages are in-line and quite common I suggest to make it conditional (guarded by a flag). It is possible to recover all 3 values from generated code if needed and turn on error reporting (specify the diagnostic flag) when reproducing failures.

src/hotspot/cpu/x86/x86_64.ad line 7029:

> 7027: %}
> 7028: 
> 7029: instruct castLL_checked(rRegL dst, rRegL tmp, rFlagsReg cr)

Optimization idea: considering the range is statically known, `tmp` is not needed when range boundaries fit into signed int. Worth adding an extra AD instruction to benefit from that.

src/hotspot/share/opto/c2_globals.hpp line 666:

> 664:           "perform extra checks on the results of alias analysis")          \
> 665:                                                                             \
> 666:   develop(uint, VerifyConstraintCasts, 0,                                   \

Any downsides in making the flag diagnostic? It'll make it available in product builds.

-------------

PR Review: https://git.openjdk.org/jdk/pull/22880#pullrequestreview-2602312430
PR Review Comment: https://git.openjdk.org/jdk/pull/22880#discussion_r1946868607
PR Review Comment: https://git.openjdk.org/jdk/pull/22880#discussion_r1946871722
PR Review Comment: https://git.openjdk.org/jdk/pull/22880#discussion_r1946882298
PR Review Comment: https://git.openjdk.org/jdk/pull/22880#discussion_r1946887184
PR Review Comment: https://git.openjdk.org/jdk/pull/22880#discussion_r1946881494


More information about the hotspot-compiler-dev mailing list