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

Vladimir Ivanov vlivanov at openjdk.org
Tue Apr 8 00:49:14 UTC 2025


On Sat, 5 Apr 2025 06:51:34 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 incrementally with one additional commit since the last revision:
> 
>   make the flag diagnostic

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

> 858:   movl(c_rarg1, type->_lo);
> 859:   movl(c_rarg2, type->_hi);
> 860:   call(RuntimeAddress(CAST_FROM_FN_PTR(address, abort_checked_cast_int)));

Do you need to align stack pointer before the call? It may be the reason why stack traces aren't printed.

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

> 865: 
> 866: static void abort_checked_cast_long(jlong val, jlong lo, jlong hi) {
> 867:   fatal("Invalid CastLL, val: %lld, lo: %lld, hi: %lld", (long long)val, (long long)lo, (long long)hi);

There's `JLONG_FORMAT` to pretty-print jlongs.

src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp line 47:

> 45:   void fast_unlock_lightweight(Register obj, Register reg_rax, Register t, Register thread);
> 46: 
> 47:   void checked_cast_int(const TypeInt* type, Register val);

There's already some ambiguity around what "checked cast" really means (think of "CastPP" vs "CheckCastPP" vs "checkcast"). Let's not make it worse. I suggest to just name it as `verify_int[_in]_range`/`verify_long[_in]_range`.

Also, unpacking `type` (and pass low/upper bounds as arguments) would make code on receiving end a bit simpler.

And some invariants to assert: 
  * no constants (lo == hi);
  * no empty ranges (lo > hi).

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

> 7644: %{
> 7645:   predicate(VerifyConstraintCasts > 0 &&
> 7646:             Assembler::is_simm32(static_cast<const CastLLNode*>(n)->type()->is_long()->_lo) &&

I suggest to extract the range check into a helper method on CastLL and call it from  `castLL_checked_L32` and `castLL_checked` predicates.

Also, `static_cast<...>(n)` can be replaced with `n->as_CastLL()`.

test/hotspot/jtreg/compiler/c2/TestVerifyConstraintCasts.java line 39:

> 37:  * @summary Run with -Xcomp to test -XX:+StressGCM -XX:VerifyConstraintCasts=2 in debug builds.
> 38:  *
> 39:  * @run main/othervm/timeout=300 -Xbatch -Xcomp -XX:+StressGCM -XX:VerifyConstraintCasts=2 compiler.c2.TestVerifyConstraintCasts

You can have multiple `@run` directives under the same `@test`. No need to duplicate it.

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

PR Review Comment: https://git.openjdk.org/jdk/pull/22880#discussion_r2032175201
PR Review Comment: https://git.openjdk.org/jdk/pull/22880#discussion_r2032182576
PR Review Comment: https://git.openjdk.org/jdk/pull/22880#discussion_r2032208822
PR Review Comment: https://git.openjdk.org/jdk/pull/22880#discussion_r2032178151
PR Review Comment: https://git.openjdk.org/jdk/pull/22880#discussion_r2032180851


More information about the hotspot-compiler-dev mailing list