Skip to content

Iterative implementation for isSubstitutable#23445

Open
AditiS11 wants to merge 1 commit intoeclipse-openj9:masterfrom
AditiS11:iterative_impl
Open

Iterative implementation for isSubstitutable#23445
AditiS11 wants to merge 1 commit intoeclipse-openj9:masterfrom
AditiS11:iterative_impl

Conversation

@AditiS11
Copy link

@AditiS11 AditiS11 commented Mar 4, 2026

Replace recursive approach to traverse fields.
Add a helper function to iteratively traverse the fields.
Use DFS with a stack to handle nested flattened value types.

Related: #15768

Signed-off-by: Aditi Srinivas M Aditi.Srini@ibm.com

@AditiS11
Copy link
Author

AditiS11 commented Mar 4, 2026

Creating a single helper function for field iteration would require two-passes of the stack, first collecting all fields into a stack, then performing the comparison. I thought that this would increase the memory overhead.
The current approach performs comparison as fields are discovered during traversal.
Hence I thought of creating separate helper functions for isSubstitutable and hash code calculation, each maintaining its own stack for field traversal.

@theresa-m theresa-m self-requested a review March 4, 2026 13:59
@theresa-m theresa-m added comp:vm project:valhalla Used to track Project Valhalla related work labels Mar 4, 2026

struct FieldComparisonFrame
{
j9object_t lhs;
Copy link
Contributor

Choose a reason for hiding this comment

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

The value of lhs and rhs appear to be the same for each entry so I don't think they need to be saved. state is not used.

UDATA startOffset,
J9Class *clazz)
{
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it would make more sense to move this flag around isSubstitutable. Your helper code should be under J9VM_OPT_VALHALLA_VALUE_TYPES as well.

Assert_VM_notNull(lhs);
Assert_VM_notNull(rhs);
Assert_VM_true(J9OBJECT_CLAZZ(currentThread, lhs) == J9OBJECT_CLAZZ(currentThread, rhs));
rc = compareValueType(currentThread, objectAccessBarrier, lhs, rhs, startOffset, clazz);
Copy link
Contributor

Choose a reason for hiding this comment

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

You can directly return the result of compareValueType instead of creating a variable.

static bool
isSubstitutable(J9VMThread *currentThread, MM_ObjectAccessBarrierAPI objectAccessBarrier, j9object_t lhs, j9object_t rhs, UDATA startOffset, J9Class *clazz)
* Iteratively traverse the fields and determine if they are equal.
* Use depth-first search with a stack to handle nested flattened value types.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think a BFS approach would make more sense for this method so you don't need to store iterators.

goto done;
j9object_t lhsFieldObject = objectAccessBarrier.inlineMixedObjectReadObject(currentThread, frame.lhs, fieldOffset);
j9object_t rhsFieldObject = objectAccessBarrier.inlineMixedObjectReadObject(currentThread, frame.rhs, fieldOffset);
bool rc = VM_ValueTypeHelpers::acmp(currentThread, objectAccessBarrier, lhsFieldObject, rhsFieldObject);
Copy link
Contributor

Choose a reason for hiding this comment

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

There is a circular call here. acmp() calls isSubstitutable.

Copy link
Author

Choose a reason for hiding this comment

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

Although acmp() calls isSubstitutable(), it starts a new traversal frame on the referenced object. I think it will not go into an infinite recursion.

Copy link
Contributor

Choose a reason for hiding this comment

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

There could still be many method calls added to the stack if an object field has another object field.

@AditiS11 AditiS11 force-pushed the iterative_impl branch 2 times, most recently from 14eedce to ab51a40 Compare March 9, 2026 12:10
U_32 walkFlags = J9VM_FIELD_OFFSET_WALK_INCLUDE_INSTANCE;
J9ROMFieldOffsetWalkState state;

std::queue<FieldComparisonFrame> queue;
Copy link
Contributor

Choose a reason for hiding this comment

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

We do not use STL. You can implement a queue using an array.

Replace recursive approach to traverse fields.
Add a helper function to iteratively traverse the fields.
Use BFS with a queue to handle nested flattened value types.
Related: eclipse-openj9#15768

Signed-off-by: Aditi Srinivas M Aditi.Srini@ibm.com
U_32 walkFlags = J9VM_FIELD_OFFSET_WALK_INCLUDE_INSTANCE;
J9ROMFieldOffsetWalkState state;

const UDATA MAX_QUEUE_SIZE = 512;
Copy link
Author

Choose a reason for hiding this comment

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

Defined the max queue size as 512. Not sure if this is sufficient to support the behaviour of valuetypes.

Copy link
Contributor

Choose a reason for hiding this comment

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

512 should be sufficient.

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

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants