Skip to content

Implement native method to calculate hash code for valuetypes - #23502

Merged
keithc-ca merged 1 commit into
eclipse-openj9:masterfrom
AditiS11:valuetypeHashCode
Jun 4, 2026
Merged

Implement native method to calculate hash code for valuetypes#23502
keithc-ca merged 1 commit into
eclipse-openj9:masterfrom
AditiS11:valuetypeHashCode

Conversation

@AditiS11

@AditiS11 AditiS11 commented Mar 12, 2026

Copy link
Copy Markdown
  • Remove valueHashCode function
  • Add implementation for convertValueObjectAtOffsetToHash to iteratively compute hash for value objects using field values.
  • Add function inlineConvertObjectToHash to handle hash computation for both value objects and identity objects.
  • Update inlineObjectHashCode to handle hash calculation for value objects.

GC changes:

  • Update GC to skip value type hash computation during copy operations.
  • Hash calculations should be triggered by the VM when it reads the hash slot and discovers 0 in the slot.
  • Add wrapper functions convertValueToHashForObject and computeObjectAddressToHashForObject to return 0 for value types during copy operations.
  • Add convertObjectToHash as GC-side wrapper to handle hash calculation for both value and identity objects.

Test changes:

  • Add tests to verify hash code behaviour for empty and similar value classes.
  • Re-enable tests related to hash for value objects.

Fixes: #15768

This change follows the approach described in 15768(comment)

@AditiS11

AditiS11 commented Mar 12, 2026

Copy link
Copy Markdown
Author

With these changes the following OpenJDK tests are passing:

  • valhalla/valuetypes/MethodHandleTest.java
  • valhalla/valuetypes/StreamTest.java
  • valhalla/valuetypes/RecursiveValueClass.java
  • runtime/valhalla/inlinetypes/TestCloneableValue.java
  • valhalla/valuetypes/ValueObjectMethodsTest.java
  • runtime/valhalla/inlinetypes/ObjectMethods.java#compressed-class-pointers
  • runtime/valhalla/inlinetypes/ObjectMethods.java#no-verify
  • runtime/valhalla/inlinetypes/ObjectMethods.java#no-compressed-class-pointers

Passing Test:
https://hyc-runtimes-jenkins.swg-devops.com/view/Test_grinder/job/Grinder/60415/testReport/
https://hyc-runtimes-jenkins.swg-devops.com/view/Test_grinder/job/Grinder/60414/testReport/

@theresa-m
theresa-m self-requested a review March 12, 2026 16:30
@theresa-m theresa-m added comp:vm project:valhalla Used to track Project Valhalla related work labels Mar 12, 2026
@AditiS11
AditiS11 force-pushed the valuetypeHashCode branch 2 times, most recently from 29d6177 to 6f419cf Compare March 13, 2026 11:42

@theresa-m theresa-m left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

First pass.

Comment thread jcl/src/java.base/share/classes/java/lang/J9VMInternals.java Outdated
private:
protected:
public:
struct ValueTypeHashQueueEntry {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This struct and the new helper methods can be under private in this file.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I've encountered compilers that don't handle private types properly in all situations.

Comment thread runtime/oti/ObjectHash.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp
Comment thread runtime/oti/ObjectHash.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp
@AditiS11
AditiS11 marked this pull request as draft March 16, 2026 12:06
@AditiS11
AditiS11 force-pushed the valuetypeHashCode branch 3 times, most recently from 59a45e3 to 437659e Compare March 18, 2026 11:17
@AditiS11
AditiS11 marked this pull request as ready for review March 18, 2026 12:22

@theresa-m theresa-m left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What is the behavior of the ri if hashCode is called prior to all strict instance fields being set in ? The easiest way to test this out is to use the @NullRestricted annotation which will mark the instance field as strict.

Comment thread runtime/vm/BytecodeInterpreter.hpp
Comment thread runtime/vm/BytecodeInterpreter.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp
Comment thread runtime/oti/ObjectHash.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp
Comment thread runtime/oti/ObjectHash.hpp Outdated
break;
}
default:
break;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This should result in an error.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I initially thought of using Assert_VM_unreachable(), but I think it can't be used here.
Could you please suggest on what error to throw here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Use Assert_VM_unreachable() (or similar) seems reasonable; reaching line 324 means the signature is invalid - which should have been detected long before we get here.

@theresa-m theresa-m Mar 20, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think you can add a comment like https://github.com/eclipse-openj9/openj9/blob/master/runtime/oti/ObjectHash.hpp#L121 instead. edit: didn't see Keith's answer before posting this.

Comment thread runtime/oti/ObjectHash.hpp
Comment thread runtime/gc_glue_java/ObjectModel.hpp Outdated
Comment thread runtime/gc_glue_java/ObjectModel.hpp Outdated
Comment thread runtime/gc_glue_java/ObjectModel.hpp Outdated
private:
protected:
public:
struct ValueTypeHashQueueEntry {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I've encountered compilers that don't handle private types properly in all situations.

Comment thread runtime/oti/ObjectHash.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp Outdated
@AditiS11
AditiS11 force-pushed the valuetypeHashCode branch from 437659e to c5f3c7e Compare March 20, 2026 18:20
@AditiS11

Copy link
Copy Markdown
Author

What is the behavior of the ri if hashCode is called prior to all strict instance fields being set in ? The easiest way to test this out is to use the @NullRestricted annotation which will mark the instance field as strict.

It throws a compiler error: reference to hashCode() may only appear after an explicit constructor invocation

@AditiS11
AditiS11 force-pushed the valuetypeHashCode branch 2 times, most recently from 75c5db8 to 9aeaac9 Compare March 23, 2026 12:23

@theresa-m theresa-m left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I suggest summarizing how hashcodes are updated for value types or link #15768 (comment) in the description so it is easy to find.

Comment thread runtime/vm/BytecodeInterpreter.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp
Comment thread runtime/gc_glue_java/ObjectModel.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp Outdated
Comment thread runtime/gc_glue_java/ObjectModel.hpp Outdated
@AditiS11
AditiS11 force-pushed the valuetypeHashCode branch from 111a450 to 01beea1 Compare March 24, 2026 12:37
Comment thread runtime/gc_glue_java/ObjectModel.hpp Outdated
@AditiS11
AditiS11 marked this pull request as draft March 25, 2026 11:37
@dmitripivkine

Copy link
Copy Markdown
Contributor

Sorry, I probably missed something, I was under impression that during VT hash code calculation if visited sub-object has hash code stored in the slot already, this code can be used instead of walking this object again. Is it right? If so, where it is implemented in the code? Just want to double check.

@AditiS11

Copy link
Copy Markdown
Author

Sorry, I probably missed something, I was under impression that during VT hash code calculation if visited sub-object has hash code stored in the slot already, this code can be used instead of walking this object again. Is it right? If so, where it is implemented in the code? Just want to double check.

https://github.com/eclipse-openj9/openj9/pull/23502/changes#diff-9aa50703bc7320e2410d7093b1f619ded056a3aeed5f75e2477603d7a5772712R269-R329
The current implementation relies on inlineObjectHashCode() for reference fields. This helper checks whether the object already has a hash stored in its hash slot and returns it if present; otherwise it computes and stores a new one.

For value types, the hash slot is not checked, and the current implementation walks through all the fields to compute the hash.

@AditiS11

Copy link
Copy Markdown
Author

Sorry about the delay. I have updated the changes.

Comment thread runtime/gc_glue_java/ObjectModel.hpp Outdated

uint32_t *hashCodePointer = (uint32_t*)((uint8_t*) destinationObjectPtr + hashOffset);
*hashCodePointer = convertValueToHash(_javaVM, (uintptr_t)forwardedHeader->getObject());
int32_t *hashCodePointer = (int32_t*)((uint8_t*)destinationObjectPtr + hashOffset);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If you are going to touch code after this point please add spaces before stars:
int32_t *hashCodePointer = (int32_t *)((uint8_t *)destinationObjectPtr + hashOffset);

Comment thread runtime/oti/ObjectHash.hpp Outdated
@AditiS11
AditiS11 force-pushed the valuetypeHashCode branch from ef15912 to 362e893 Compare June 1, 2026 10:53
Comment thread runtime/gc_glue_java/ObjectModel.hpp Outdated
Comment thread runtime/gc_glue_java/ObjectModel.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp
Comment thread runtime/oti/ObjectHash.hpp Outdated
Comment thread runtime/oti/ObjectHash.hpp
Comment thread test/functional/Valhalla/src_qtypes/org/openj9/test/lworld/ValueTypeTests.java Outdated
@AditiS11
AditiS11 force-pushed the valuetypeHashCode branch 2 times, most recently from 65e7666 to fb05683 Compare June 2, 2026 12:37

@keithc-ca keithc-ca left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please squash and rebase.

@AditiS11
AditiS11 force-pushed the valuetypeHashCode branch from fb05683 to 4f1b712 Compare June 2, 2026 15:44
@keithc-ca keithc-ca changed the title Implement native method to calculate hashcode for valuetypes Implement native method to calculate hash code for valuetypes Jun 2, 2026
@keithc-ca

keithc-ca commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Please update the commit message to spell "hash code" consistently (two words), punctuate consistently, and ensure that no line in the body is more than 72 characters long.

- Remove valueHashCode function.
- Add implementation for convertValueObjectAtOffsetToHash to
  iteratively compute hash codes for value objects using field
  values.
- Add function inlineConvertObjectToHash to handle hash
  computation for both value objects and identity objects.
- Update inlineObjectHashCode to handle hash calculation for
  value objects.

GC changes:

- Update GC to skip value type hash computation during copy
  operations.
- Hash calculations should be triggered by the VM when it reads
  the hash slot and discovers 0 in the slot.
- Add wrapper functions convertValueToHashForObject and
  computeObjectAddressToHashForObject to return 0 for value
  types during copy operations.
- Add convertObjectToHash as a GC-side wrapper to handle hash
  calculation for both value and identity objects.

Test changes:

- Add tests to verify hash code behaviour for empty and similar
  value classes.
- Re-enable tests related to hash codes for value objects.

Fixes: eclipse-openj9#15768

Signed-off-by: Aditi Srinivas M <Aditi.Srini@ibm.com>
@AditiS11
AditiS11 force-pushed the valuetypeHashCode branch from 4f1b712 to f59105c Compare June 3, 2026 12:45
@keithc-ca

Copy link
Copy Markdown
Contributor

The commit message is much better. Thank you.

@keithc-ca

Copy link
Copy Markdown
Contributor

Jenkins test sanity,extended aix,amac,plinux,win jdk25

@hangshao0

Copy link
Copy Markdown
Contributor

Jenkins test sanity.functional,extended zlinuxval jdknext

@hangshao0

Copy link
Copy Markdown
Contributor

jenkins compile win,win32 jdk8

@github-project-automation github-project-automation Bot moved this from TODO: VM to Needs review in Valhalla L-World Jun 3, 2026
* @return finalized hash value
*/
static VMINLINE U_32
finalizeMurmur3Hash(U_32 hashValue, U_32 numBytesHashed)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

DDR should be updated to match these changes; see ObjectHash.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I created #24053 to track that (future) work.

@keithc-ca

Copy link
Copy Markdown
Contributor

The one test failure appears to be a known issue: #21871.

@github-project-automation github-project-automation Bot moved this from Needs review to Reviewer approved in Valhalla L-World Jun 4, 2026
@keithc-ca
keithc-ca merged commit 0490c4c into eclipse-openj9:master Jun 4, 2026
23 of 25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp:gc comp:vm project:valhalla Used to track Project Valhalla related work

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Create native function to compute hashcodes for value types

6 participants