[lworld] RFR: 8375441: [lworld] C2: assert(is_instance()) failed: bad cast [v2]
Quan Anh Mai
qamai at openjdk.org
Mon Feb 2 16:38:57 UTC 2026
On Wed, 28 Jan 2026 09:19:18 GMT, Marc Chevalier <mchevalier at openjdk.org> wrote:
>> Some code added by [JDK-8372700](https://bugs.openjdk.org/browse/JDK-8372700) can compute the constant value of a field of a (flatten) element in a flat array. We get a crash when the element of the array is known to be `null`, and so the field doesn't exist.
>>
>> So, let's just check in `ciConstant ciFlatArray::field_value(int index, ciField* field)` whether we get a null constant before interpreting it as a `ciInstance` and trying to retrieve a field from there. This should be enough since a `ciObject` is (directly) derived by `ciNullObject`, `ciInstance` and `ciArray`. Since we are looking up a value of a flat array, an element cannot be a `ciArray` (arrays have identities and can't be contained in a flat array). After looking up whether the flat array element is null, the `obj->as_instance()` cast acts as an assert, should we ever add another derived class from `ciObject`.
>>
>> In case of a null array element, `field_value` simply returns an invalid `ciConstant`.
>>
>> Tested with tier1,tier2,tier3,hs-precheckin-comp,hs-comp-stress,valhalla-comp-stress. Looks good.
>>
>> Thanks,
>> Marc
>
> Marc Chevalier has updated the pull request incrementally with 10 additional commits since the last revision:
>
> - Details
> - exception handling
> - oops
> - Also cache correctly whole stable fields
> - fix comment
> - Remove debug
> - ShouldNotReachHere
> - explicit casts
> - Clean up
> - expand_constant
Thanks a lot for working on this, I have a couple of comments.
src/hotspot/share/ci/ciInstance.cpp line 86:
> 84: InstanceKlass* holder = InstanceKlass::cast(obj->klass());
> 85: int index = -1;
> 86: for (JavaFieldStream fs(holder); !fs.done(); fs.next()) {
My latest PR should include a `_layout_kind` in the `ciField` object, can you use it?
src/hotspot/share/ci/ciInstance.cpp line 95:
> 93: InlineLayoutInfo* layout_info = holder->inline_layout_info_adr(index);
> 94: InlineKlass* vk = layout_info->klass();
> 95: oop res = vk->read_payload_from_addr(obj, offset, layout_info->kind(), THREAD);
It seems to imply that this access is required to be atomic, what if it is a non-atomic field?
src/hotspot/share/ci/ciInstance.cpp line 137:
> 135: // desired field. If we want a sub-field of a flat field, we then extract the field
> 136: // out of the cached copy.
> 137: ciConstant ciInstance::field_value(ciField* field) {
Similarly, what kind of field is expected here, is it a declared field, or a primitive subfield?
src/hotspot/share/ci/ciInstance.cpp line 144:
> 142: ciInstanceKlass* klass = this->klass()->as_instance_klass();
> 143: ciField* containing_field;
> 144: if (field->original_holder() == nullptr) {
Is this branch necessary, I thought `klass->field_index_by_offset` should give the correct result if `field` is not a subfield?
src/hotspot/share/ci/ciInstance.cpp line 154:
> 152: return ciConstant();
> 153: }
> 154: if (field->original_holder() == nullptr) {
I think simply comparing `field` and `containing_field` is enough.
src/hotspot/share/ci/ciInstance.cpp line 175:
> 173: // Extract a field from a value object.
> 174: // This won't cache. Must be used only on cached values.
> 175: ciConstant ciInstance::non_flat_field_value(ciField* field) {
Can you specify which kind of `field` is required here. I would assume this is a declared field that is not a flat field.
src/hotspot/share/ci/ciInstanceKlass.cpp line 440:
> 438: }
> 439:
> 440: int ciInstanceKlass::field_index_by_offset(int offset) {
Why is assert needs removing?
src/hotspot/share/opto/compile.cpp line 2106:
> 2104: ciInstance* loaded_from = nullptr;
> 2105: if (FoldStableValues) {
> 2106: const TypeOopPtr* base_type = igvn.type(loadn->base())->isa_oopptr();
Normally, `isa_...` methods are only used if we want to null check it, otherwise, use the corresponding `is_...` method.
src/hotspot/share/opto/compile.cpp line 2125:
> 2123: } else if (oop != nullptr && oop->is_array()) {
> 2124: ciArray* array = oop->as_array();
> 2125: ciConstant elt = array->element_value_by_offset(off);
IIUC, `off` can be `Type::OffsetBot` here, I think it would be better to handle it here because it is an implementation detail that should not be visible to `ci`.
-------------
PR Review: https://git.openjdk.org/valhalla/pull/1923#pullrequestreview-3740519059
PR Review Comment: https://git.openjdk.org/valhalla/pull/1923#discussion_r2755233617
PR Review Comment: https://git.openjdk.org/valhalla/pull/1923#discussion_r2755235862
PR Review Comment: https://git.openjdk.org/valhalla/pull/1923#discussion_r2755208953
PR Review Comment: https://git.openjdk.org/valhalla/pull/1923#discussion_r2755222711
PR Review Comment: https://git.openjdk.org/valhalla/pull/1923#discussion_r2755226019
PR Review Comment: https://git.openjdk.org/valhalla/pull/1923#discussion_r2755200089
PR Review Comment: https://git.openjdk.org/valhalla/pull/1923#discussion_r2755239944
PR Review Comment: https://git.openjdk.org/valhalla/pull/1923#discussion_r2755166332
PR Review Comment: https://git.openjdk.org/valhalla/pull/1923#discussion_r2755181723
More information about the valhalla-dev
mailing list