[lworld] RFR: 8335256: [lworld] compiler/valhalla/inlinetypes/TestValueConstruction.java fails intermittently [v3]
Jatin Bhateja
jbhateja at openjdk.org
Thu Feb 13 11:28:29 UTC 2025
On Tue, 11 Feb 2025 15:51:04 GMT, Quan Anh Mai <qamai at openjdk.org> wrote:
>> Hi,
>>
>> The assert fires because in this place:
>>
>> if (is_osr_parse()) {
>> Node* osr_buf = entry_map->in(TypeFunc::Parms+0);
>> entry_map->set_req(TypeFunc::Parms+0, top());
>> set_map(entry_map);
>> load_interpreter_state(osr_buf);
>> } else {
>> set_map(entry_map);
>> do_method_entry();
>> }
>>
>> `load_interpreter_state` assumes that all incoming inline types are non-larval, while in the following place:
>>
>> if (t->is_inlinetypeptr()) {
>> // Create InlineTypeNode from the oop and replace the parameter
>> bool is_larval = (i == 0) && method()->is_object_constructor() && !method()->holder()->is_java_lang_Object();
>> Node* vt = InlineTypeNode::make_from_oop(this, parm, t->inline_klass(), !t->maybe_null(), is_larval);
>> replace_in_map(parm, vt);
>> }
>>
>> `is_larval == true` because we are osr-compiling the constructor of a value class. As a result, we pass a non-larval object into `InlineTypeNode::make_from_oop` and want to make it larval, triggering the assert.
>>
>> Thinking more deeply into this, I think there is no way we can know the larval-ness of an incoming object in an osr-compilation unless `ciTypeFlow` does so. For example, consider this bytecode sequence:
>>
>> ValueObject x = new ValueObject;
>> for {
>> }
>> x.<init>();
>>
>> Then, when we osr-compile the method from the loop, `x` will be a larval object and it can be at any place on the JVM stack or in the local slots.
>>
>> As a result, I propose optimistically assuming all osr parameters be non-larval, then we can change them to larval when encountering a constructor invocation or a field store instruction. The verifier should ensure that we cannot do anything else on a larval object as well as do these actions on a non-larval object, so we should recognize the correct state of the value object if any operation is performed on them. Otherwise, they should be dead and not apear here.
>>
>> Please take a look and give your advices, 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 three additional commits since the last revision:
>
> - Merge branch 'lworld' into osrinlinetype
> - typo
> - Fix osr inline type parameter
src/hotspot/share/opto/doCall.cpp line 588:
> 586: // optimistically assume all parameters are non-larval. Then, a parameter is changed to larval
> 587: // if we encounter a store into one of its fields, or if we encounter a constructor invocation
> 588: // with it being the first argument
The implicit larval transition has a limited life span, it begins from the new allocation and ends just before exiting constructor.
[https://github.com/openjdk/valhalla/blob/d94c58952d2f9a0193af4cd9df66868fd0a6e3db/src/hotspot/share/opto/doCall.cpp#L830](https://github.com/openjdk/valhalla/blob/d94c58952d2f9a0193af4cd9df66868fd0a6e3db/src/hotspot/share/opto/doCall.cpp#L830
)
The only possibility to create a larval value that gets passed on to OSR buffer is by explicitly marking it as larval using Unsafe.makePrivateBuffer API before the loop.
May I request you to kindly add a new or identify an existing test case for this scenario
-------------
PR Review Comment: https://git.openjdk.org/valhalla/pull/1358#discussion_r1954316155
More information about the valhalla-dev
mailing list