On Thu, 5 Nov 2026 15:17:04 GMT, Quan Anh Mai <[email protected]> wrote:

> ## Problem
> 
> When C2 parses a variable, it tries to be smart about the type of that 
> variable. If a method parameter declares that it is of type `A`, and `A` is 
> an abstract class that only has a single concrete subclass `B`, then C2 
> eagerly assumes that the parameter must be of type `B`. This property, in the 
> presence of concurrent class loading/unloading, does not always hold, as the 
> VM can always load another concrete subclass `C` of `A` that is unrelated to 
> `B`. To avoid incorrect execution arised from this issue, C2 relies on 
> `dependencies`, which encodes various kinds of assumptions the compiler made. 
> Among those, we have an assumption called `unique_concrete_subclass`, which 
> will be invalidated when `C` is loaded, triggering the deoptimization and 
> invalidation of the aforementioned compiled method.
> 
> However, this mechanism is both inadequate and not timely. The main issue is 
> that the concurrent load of `C` may not only happen after the compilation has 
> finished, but also during the compilation process. This leads to CHA 
> computation giving contradictory results when called at different time in the 
> compilation process. There are 2 examples which were reported:
> 
> 1.
> 
>     if (b) {
>         A a1 = ...;
>     } else {
>         C a2 = ...;
>     }
>     A a = Phi(a1, a2);
> 
> If `A a = Phi(a1, a2)` is parsed before `C a2 = ...`, and `C` has not been 
> loaded then, the compiler will assume that `a` must be of type `B`. This 
> leads to a `Phi` of type `B` with one of its inputs being a node of type `C` 
> which is unrelated. This graph shape is nonsense, and all kinds of issues can 
> appear from various optimization passes which do not expect such a 
> conflicting graph.
> 
> 2.
> 
>     A a = call();
> 
> If when `a` is parsed, `C` has not been loaded, the compiler will assume `a` 
> is of type `B`. However, if `call` is late-inlined, and it turns out that the 
> returned value is of type `C`. All uses of `a` will suddenly have their input 
> changed from a `B` to a `C`, which may also lead to unexpected failures.
> 
> ## Overview of this PR
> 
> This PR tries to detect CHA inconsistencies, and triggers a compilation 
> failure when such a paradox happens. The core invariant that needs holding is 
> that, given type `X` and `Y`, if `X` is a subtype of `Y`, then the result of 
> narrowing `X` should also be a subtype of the result of narrowing `Y`. This 
> invariant does not need to hold in the VM, it only needs to hold in the local 
> `ciEnv`, which is the local view of the compiler with respect to the class 
> hierarchy.
> 
> In some...

src/hotspot/share/code/dependencies.cpp line 114:

> 112: void Dependencies::assert_unique_implementor(ciInstanceKlass* ctxk, 
> ciInstanceKlass* uniqk) {
> 113:   check_ctxk(ctxk);
> 114:   check_unique_implementor(ctxk, uniqk);

I don't think this check is ensured, so I removed it.

src/hotspot/share/opto/parse1.cpp line 2511:

> 2509:     return vt;
> 2510:   } else {
> 2511:     PhiNode* phi = new PhiNode(region, t);

The changes in this file are to revert 
[JDK-8387328](https://bugs.openjdk.org/browse/JDK-8387328). I tried inserting 
an assert here that `o->bottom_type()` must be a subset of `t`, but there are 
some issues with method handle intrinsics that prevent this. To be specific, I 
find that a method is supposed to return `BoundedMethodHandle`, but the 
`ProjNode` is an `Object`.

src/hotspot/share/opto/phaseX.cpp line 1248:

> 1246: static bool klass_bottom_type_invalidated(const Node* n, const Type* 
> new_type) {
> 1247:   // Concurrent class loading can invalidate a klass bottom type.
> 1248:   const Type* bt = n->bottom_type();

The changes in this file and `phaseX.hpp` are to revert 
[JDK-8393482](https://bugs.openjdk.org/browse/JDK-8393482).

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

PR Review Comment: https://git.openjdk.org/jdk/pull/33753#discussion_r4528391440
PR Review Comment: https://git.openjdk.org/jdk/pull/33753#discussion_r4528375809
PR Review Comment: https://git.openjdk.org/jdk/pull/33753#discussion_r4528381483

Reply via email to