[lworld] RFR: 8321734: [lworld] C2: flat_in_array type is not handled correctly leading to crashes
Christian Hagedorn
chagedorn at openjdk.org
Fri Apr 19 11:34:40 UTC 2024
On Fri, 19 Apr 2024 11:13:50 GMT, Christian Hagedorn <chagedorn at openjdk.org> wrote:
> There are multiple issues around types being `flat_in_array`:
>
> #### 1. `SubTypeCheckNode` is not folded while `CheckCastPP` is correctly replaced by top due to an impossible type:
> Test: `testSubTypeCheckNotFoldedParsingAbstractClass():`
>
> We have the following:
> - `PUnique` is the unique concrete value sub class of the abstract value `AUnique` class
> - `Object[] arr` -> elements could be an inline type that is flat
>
> We apply loop unswitching such that we have a loop where the access `arr[i]` is with a flat inline type (i.e. marked as flat-in-array) and one version without. In the flat-in-array loop, we have the following sub type check for the `checkcast` for `(AUnique)arr[i]`:
>
> AUnique [maybe-flat-in-array] <: Object [flat-in-array]
>
> Since we do not know if `AUnique` is flat-in-array, we cannot fold this check. However, the corresponding `CheckCastPP` for this sub type check uses the unique concrete sub class `PUnique` which is known to be *not*-flat-in-array with `FlatArrayElementMaxSize=4`. Since a not-flat-in-array type cannot be a sub type of a flat-in-array type (determined during class loading), the `CheckCastPP` is replaced by top. But the `SubTypeCheck` is not folded.
>
> This was found in Valhalla and fixed in mainline with JDK-8328480. I've added the Valhalla specific test and merged the fix from mainline into this patch.
>
> #### 2. Wrong `not_flat_in_array` default value
> Test: `testSubTypeCheck()` and `testCmpP()`:
> Arrays are always normal objects (i.e. not inline types). They are therefore never flat-in-array and always not-flat-in-array. While they are correctly never marked as flat-in-array, they are currently not marked as *not*-flat-in-array and thus have the implicit state *maybe*-flat-in-array:
> https://github.com/openjdk/valhalla/blob/e01ec832189453cc302c7ca8915e69bb63a3d4b1/src/hotspot/share/opto/type.hpp#L1096
>
> This becomes a problem for `SubTypeCheck` and `CmpP` nodes which cannot determine that a flat-in-array klass and an array klass are unrelated. But the type system itself correctly treat arrays as *not*-flat-in-array when doing a meet operation. As a result, data is folded while control is not.
>
> This is fixed by changing the flat-in-array tri-state: As a default, a type is always not-flat-in-array. Inline types then override this property accordingly.
>
> #### 3. Type system wrongly treats "maybe-be-flat-in-array <: flat-in-array" as top
> Test: `testUnswitchingAbstractClass()`
> "maybe-be-flat-in-array <: flat-in-array" should not be treate...
src/hotspot/share/opto/graphKit.cpp line 3451:
> 3449: const TypeKlassPtr* klass_ptr_type = _gvn.type(superklass)->is_klassptr();
> 3450: const TypeKlassPtr* improved_klass_ptr_type = klass_ptr_type->try_improve();
> 3451: const TypeOopPtr* toop = improved_klass_ptr_type->cast_to_exactness(false)->as_instance_type();
Changes in this file taken from JDK-8328480.
src/hotspot/share/opto/type.cpp line 997:
> 995:
> 996: // Verify that:
> 997: // this meet t == t meet this
Found these comments useful while verifying the type system changes.
src/hotspot/share/opto/type.cpp line 4536:
> 4534: const bool other_flat_in_array = other_type->flat_in_array();
> 4535: const bool this_not_flat_in_array = this_type->not_flat_in_array();
> 4536: const bool other_not_flat_in_array = other_type->not_flat_in_array();
`this_flat_in_array` and `flat_array` are both used to hold intermediate and final results about whether the type is going to be flat-in-array or not. This was somewhat hard to follow what was going on.
Changed this into: `this_flat_in_array` for the flat-in-array state of `this_type` and `flat_in_array` to hold the intermediate and eventually the final result assigned to `res_flat_in_array`.
src/hotspot/share/opto/type.cpp line 4582:
> 4580: subtype_exact = below_centerline(ptr) ? (this_xk && other_xk) : (this_xk || other_xk);
> 4581: flat_array = below_centerline(ptr) ? (this_flat_in_array && other_flat_in_array) : (this_flat_in_array || other_flat_in_array);
> 4582: } else if (!other_xk && this_type->is_meet_subtype_of(other_type) && (!other_flat_in_array || this_flat_in_array)) {
Extracted `is_meet_subtype_of()` + flat-in-array checks to separate methods to simplify the condition.
src/hotspot/share/opto/type.cpp line 4604:
> 4602: other_type = this_type; // this is down; keep down man
> 4603: other_xk = this_xk;
> 4604: other_flat_in_array = this_flat_in_array;
Assignments to `other*` are not used anymore later and are thus removed.
-------------
PR Review Comment: https://git.openjdk.org/valhalla/pull/1079#discussion_r1572215555
PR Review Comment: https://git.openjdk.org/valhalla/pull/1079#discussion_r1572215040
PR Review Comment: https://git.openjdk.org/valhalla/pull/1079#discussion_r1572228027
PR Review Comment: https://git.openjdk.org/valhalla/pull/1079#discussion_r1572220233
PR Review Comment: https://git.openjdk.org/valhalla/pull/1079#discussion_r1572216420
More information about the valhalla-dev
mailing list