Implement fast and slow value object hash paths#24356
Conversation
8fac93c to
a8c82ae
Compare
|
50X Grinder for the test: https://hyc-runtimes-jenkins.swg-devops.com/view/Test_grinder/job/Grinder/61372/testReport/ |
| bool depthExceeded = false; | ||
| I_32 hashValue = recursiveValueObjectHash(vm, currentThread, objectPointer, clazz, startOffset, 0, &depthExceeded, oomOccurred); | ||
| if (!depthExceeded || *oomOccurred) { | ||
| return hashValue; |
There was a problem hiding this comment.
Shouldn't the method return here regardless of the value of oomOccurred?
| if (NULL == entry->currentField->field) { | ||
| U_32 finalHash = finalizeMurmur3Hash(entry->hashValue, entry->numBytesHashed); | ||
| if (0 == finalHash) { | ||
| finalHash = 1; |
There was a problem hiding this comment.
Can you add back the comment that was here for clarity?
/* Hash code for value types should not be zero. */
| default: | ||
| /* Invalid field signature. Should assert but we are in util. */ | ||
| break; | ||
| if (*depthExceeded || *oomOccurred) { |
There was a problem hiding this comment.
Would oomOccurred ever be true here?
There was a problem hiding this comment.
No Theresa, oomOccurred would never be true in the recursive path. Will remove this.
|
I suggest adding a debugging -XX option (sth like -XX:VTHashRecDepth=n) to overwrite the default J9_VALUE_TYPE_HASH_DEPTH_LIMIT. This could help us diagnose issues with fastpath vs slowpath implementations. |
| UDATA depth = 0; | ||
| char *optname = VMOPT_HASHMAXRECDEPTH_EQUALS; | ||
| GET_INTEGER_VALUE(argIndex, optname, depth); | ||
| if (0 != depth) { |
There was a problem hiding this comment.
I think 0 should be allowed in case we want to test the slow path only.
| frame->hashValue = getSalt(vm, (UDATA)frame->objectPointer, true); | ||
| frame->hashValue = mix(frame->hashValue, (U_32)(UDATA)frame->clazz); | ||
| frame->numBytesHashed = sizeof(UDATA); | ||
| frame->currentField = vm->internalVMFunctions->fieldOffsetsStartDo(vm, frame->clazz->romClass, VM_VMHelpers::getSuperclass(frame->clazz), |
There was a problem hiding this comment.
Please put each of the arguments on a separate line.
|
|
||
| /** | ||
| * Fast-path recursive hash computation for value objects. | ||
| * Used if recursive depth is less than J9_VALUE_TYPE_HASH_DEPTH_LIMIT. |
There was a problem hiding this comment.
J9_VALUE_TYPE_HASH_DEPTH_LIMIT doesn't exist anymore. Also in line 495.
- Use the recursive fast path for value object hash computation. - Use the fast path while the recursion depth is below J9_VALUE_TYPE_HASH_DEPTH_LIMIT. - Switch to the iterative path when the recursion depth limit is exceeded. - Use a DFS-based queue to traverse value object fields in the iterative path. - Add -XX:hashMaxRecDepth debug option to override default recursion depth. Fixes: eclipse-openj9#24087 Signed-off-by: Aditi Srinivas M <Aditi.Srini@ibm.com>
| IDATA parentIndex; | ||
| }; | ||
|
|
||
| struct ValueTypeHashQueue { |
There was a problem hiding this comment.
This becomes more of a stack than a queue ?
There was a problem hiding this comment.
Yes Hang its a stack. I just kept the naming the same as the original code to minimize the diff.
I will change the naming.
| { | ||
| if (full) { | ||
| UDATA newTop = (UDATA)(top + 1); | ||
| if (newTop >= capacity) { |
There was a problem hiding this comment.
Why not check if (newTop == capacity) only ?
There was a problem hiding this comment.
I just added >= as a defensive check. Will change it to newTop == capacity
| UDATA hashSlotOffset = fieldClazz->backfillOffset; | ||
| storedHash = objectAccessBarrier.inlineMixedObjectReadI32(currentThread, fieldObject, hashSlotOffset); | ||
| } | ||
| if (0 != storedHash) { |
There was a problem hiding this comment.
I think for non-VT field, its hash can be 0. So if the storedHash is 0 in this case, it can still be used.
The same comment apply to the slowpath.
There was a problem hiding this comment.
Based on the analysis of one of the benchmark logs, we didn't observe any cases where identity types had a hash value of 0. Hence I assumed this scenario wouldn't occur.
|
@hangshao0 How we guarantee that object pointers stored during calculation (slow path particularly) are not becoming stale? Do we assume hash code calculation executes under VM Access always to prevent GC?
|
|
The code here in this PR assumes the object pointers are non-stale.
We should have an assertion for this. However, there were review comments on adding assertions in ObjectHash,hpp in Aditi's previous hashcode implementation PR. but it seems assertions cannot be added into this file (don't recalled the details back then). If that is the case, I think assertion should be added to the callers in other files for VM access (it should be taken if not already taken).
I expect VT objects are mostly leaves of the data tree that does not delay GC too long for the hash calculation. |
|
yes, assertion can be tricky here |
Fixes: #24087