Hi, Currently, C2 eagerly expands an oop leaf field of a value class if that leaf field has its type being a value class, this happens recursively, as long as there is no cycle. This eagerness may help the compiler have a better chance optimizing merging value types, as the `InlineTypeNode` is pushed down through the `Phi`s, allows C2 to fold the loads better. However, this expansion is unbounded, which means at any parsing or IGVN step, the compiler may emit an unbounded amount of nodes.
This PR removes this eagerness, that is, it makes the compiler not try expanding a value object subfield, unless the field is loaded. This removes the unbounded nature of value object expansion, it also makes the compiler emit less node, which alleviate the pressure on other optimizations in extreme cases. In most case, this does not change the behaviour of C2, as value objects are aggressively flattened inside other value objects, unless their `LooselyConsistentValue` mismatch, which is not an issue for JEP 401. It also means that, we have no choice but stopping flattening at this level, because going even 1 level deeper may lead to issues in extreme cases, as a value object can have hundreds of leaf fields. This is demonstrated in the added regression test. `V1` is fully flattened, `V0` flattens only its first field, so if we also expand the leaf fields of `V0`, we will expand the object fully, leading to an explosion of node number. There are mutliple test failures due to the compiler not able to fold through a load from a `Phi` of `InlineTypeNode`s. This will need fixing after JEP 401. I encounted a tricky issue with load folding from a value object, which is exposed by this patch. That is, when we push a `CastPP` through an `InlineTypeNode`, we need to cast all of its oop field that is null-free to not null. This is because we inject the information that those fields are null-free into the loads, but the inputs of the `InlineTypeNode` can be `null`, because the `InlineTypeNode` itself is nullable. As a result, when the load looks through the `Cast` to the `InlineTypeNode`, it misses the dependency of the `Cast` that it just looked through, dropping the constraint that the loaded value must be not null. As a result, it can be scheduled before the null check, resulting in a crash. The fix is to unconditionally push a cast to not-null through its `InlineTypeNode` input, to add `CastPP` of null-free inputs to not-null, and to remove the ability of `see_through_inline_type` to look through `ConstraintCast`s. Testing: - [x] tier1-4,valhalla-comp-stress Please take a look and leave your review, thanks a lot. --------- - [x] I confirm that I make this contribution in accordance with the [OpenJDK Interim AI Policy](https://openjdk.org/legal/ai). ------------- Commit messages: - Restrict scalarization of nested value objects Changes: https://git.openjdk.org/valhalla/pull/2474/files Webrev: https://webrevs.openjdk.org/?repo=valhalla&pr=2474&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8370769 Stats: 553 lines in 14 files changed: 266 ins; 158 del; 129 mod Patch: https://git.openjdk.org/valhalla/pull/2474.diff Fetch: git fetch https://git.openjdk.org/valhalla.git pull/2474/head:pull/2474 PR: https://git.openjdk.org/valhalla/pull/2474
