Skip to content

8382226: [lworld] C2: Fix _copyOf/_copyOfRange intrinsic for flat abstract value class arrays#2569

Open
chhagedorn wants to merge 4 commits into
openjdk:lworldfrom
chhagedorn:JDK-8382226
Open

8382226: [lworld] C2: Fix _copyOf/_copyOfRange intrinsic for flat abstract value class arrays#2569
chhagedorn wants to merge 4 commits into
openjdk:lworldfrom
chhagedorn:JDK-8382226

Conversation

@chhagedorn

@chhagedorn chhagedorn commented Jun 19, 2026

Copy link
Copy Markdown
Member

The provided test cases fail when inlining the Array.copyOf/copyOfRange() intrinsics where the source array is flat and from an abstract value class.

The current code checks whether the source array or the destination array klass contain oops by assuming that a flat value class array is always concrete and thus an InlineKlass (i.e. can call inline_klass()). However, we could also have abstract value class arrays that are known to be flat (see test cases). This leads to a cast assertion failure because abstract value classes are represented by an InstanceKlass and not an InlineKlass.

To fix this, I added a simple bailout when detecting an abstract flat value class array. This is a conservative correctness fix and should be revisited again post-Valhalla-integration. We have JDK-8251971 in place for that which should also tackle other issues around the arraycopy intrinsics and also address performance problems.

Thanks,
Christian



Progress

  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue
  • Change must be properly reviewed (1 review required, with at least 1 Committer)

Issue

  • JDK-8382226: [lworld] C2: Fix _copyOf/_copyOfRange intrinsic for flat abstract value class arrays (Bug - P4)

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/valhalla.git pull/2569/head:pull/2569
$ git checkout pull/2569

Update a local copy of the PR:
$ git checkout pull/2569
$ git pull https://git.openjdk.org/valhalla.git pull/2569/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 2569

View PR using the GUI difftool:
$ git pr show -t 2569

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/valhalla/pull/2569.diff

Using Webrev

Link to Webrev Comment

@bridgekeeper

bridgekeeper Bot commented Jun 19, 2026

Copy link
Copy Markdown

👋 Welcome back chagedorn! A progress list of the required criteria for merging this PR into lworld will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk

openjdk Bot commented Jun 19, 2026

Copy link
Copy Markdown

❗ This change is not yet ready to be integrated.
See the Progress checklist in the description for automated requirements.

@openjdk openjdk Bot added the rfr Pull request is ready for review label Jun 19, 2026
@mlbridge

mlbridge Bot commented Jun 19, 2026

Copy link
Copy Markdown

Webrevs

Comment thread src/hotspot/share/opto/library_call.cpp Outdated
const TypeAryPtr* orig_t = _gvn.type(original)->isa_aryptr();
const TypeKlassPtr* tklass = _gvn.type(klass_node)->is_klassptr();
bool exclude_flat = UseArrayFlattening && bs->array_copy_requires_gc_barriers(true, T_OBJECT, false, false, BarrierSetC2::Parsing) &&
const bool is_src_abstract_flat_value_array = orig_t != nullptr && !orig_t->elem()->is_inlinetypeptr() && orig_t->is_flat();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we check for !orig_t->is_not_flat() instead?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good idea to cover all the cases where it could be flat. Updated this and the check for tklass as well accordingly.

Comment thread src/hotspot/share/opto/library_call.cpp Outdated
(orig_t == nullptr || (!orig_t->is_not_flat() && (!orig_t->is_flat() || orig_t->elem()->inline_klass()->contains_oops()))) &&
// Can dest array be flat and contain oops?
tklass->can_be_inline_array() && (!tklass->is_flat() || tklass->is_aryklassptr()->elem()->is_instklassptr()->instance_klass()->as_inline_klass()->contains_oops());
can_dest_be_value_class_array && (!tklass->is_flat() || tklass->is_aryklassptr()->elem()->is_instklassptr()->instance_klass()->as_inline_klass()->contains_oops())));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also check for tklass->is_not_flat() instead.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I also took another look at the code again and refactored it a bit to make exclude_flat easier to understand. Let me know, what you think.

tklass->can_be_inline_array() && (!tklass->is_flat() || tklass->is_aryklassptr()->elem()->is_instklassptr()->instance_klass()->as_inline_klass()->contains_oops());
const TypeAryKlassPtr* dest_klass_t = _gvn.type(klass_node)->is_klassptr()->isa_aryklassptr();
const bool can_src_be_abstract_flat_value_class_array = orig_t != nullptr && !orig_t->elem()->is_inlinetypeptr() && !orig_t->is_not_flat();
const bool can_dest_be_value_class_array = dest_klass_t != nullptr && dest_klass_t->can_be_inline_array();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if dest is not an aryklassptr? I think in that case this should also be true, right?

// Can dest array be flat and contain oops?
tklass->can_be_inline_array() && (!tklass->is_flat() || tklass->is_aryklassptr()->elem()->is_instklassptr()->instance_klass()->as_inline_klass()->contains_oops());
const TypeAryKlassPtr* dest_klass_t = _gvn.type(klass_node)->is_klassptr()->isa_aryklassptr();
const bool can_src_be_abstract_flat_value_class_array = orig_t != nullptr && !orig_t->elem()->is_inlinetypeptr() && !orig_t->is_not_flat();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This name is a little misleading, I think you want to catch the case orig_t == nullptr below, but if the static type is j.l.O, the runtime type can still be an abstract flat array.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rfr Pull request is ready for review

Development

Successfully merging this pull request may close these issues.

2 participants