JDK-6378256 : Performance problem with System.identityHashCode in client compiler
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 6,8,9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2006-01-28
  • Updated: 2016-03-03
  • Resolved: 2016-02-17
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
9 b108Fixed
Related Reports
Relates :  
As noticed in bug JDK-6182955, there appears to be a performance problem
when calling System.identityHashCode.  See that bug for a test case.

http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/2016-February/021338.html http://cr.openjdk.java.net/~thartmann/6378256/webrev.05/


Yes. Only the identity hashcode is captured in the header. Since it's just a number hotspot generates it has to be captured somewhere once it's generated. C1 generates a little snippet of assembly in the prolog of the nmethod wrapper for the native method for Object.hashCode that pulls it out of the header if the identity hash code has been computed. C2 generates that same logic inline but guarded with object->vtbl[hashCode_index] == Object.hashCode.

Thanks Tom. Not sure what interposing means here. Do we only store the hashcode() in the object header when it comes from Object.hashcode()?

Yes it is. There are two approaches, devirtualize Object.hashCode calls or interpose on the Object.hashCode implementation itself. C2 devirtualizes by testing the virtual method table and C1 interposes on Object.hashCode. That's why this code is in the nmethod wrapper generation logic.

Yes I realize that. What is not clear is whether Object.hashcode() being overridden is being taken into consideration here. ?? Thanks.

@David Holmes, the implementation of Object.hashCode() and System.identityHashCode() are same, JVM_IHashCode(). we can say if Object.hashCode() method is not overridden the same calls System.identityHashCode(this)! Also from documentation of System.identityHashCode(Object) - 'Returns the same hash code for the given object as would be returned by the default method hashCode(), whether or not the given object's class overrides hashCode(). The hash code for the null reference is zero.

I may well be missing something here but I don't see how you can store the identityHashcode of an object in the object header in general - surely you can only do that when the class's hashcode() implementation is the same as the identityHashcode() implementation.

Revised patch - http://cr.openjdk.java.net/~thartmann/6378256/webrev.02/ http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/2016-January/020956.html

Fix patch sent to open for review- (x86_32, SPARC) webrev: http://cr.openjdk.java.net/~thartmann/6378256/webrev.00/ RFR email - http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/2015-December/020322.html

update: - Unit tests tries so far worked fine for initial fix. - No issues with jtreg run tried locally for j.l.System tests. - Got 4 fails for 'jprt submit -stree . -noqa -testset hotspot ...' tried. - Analysis of fix1, jprt fails, checking other possible testing in progress.

Reproduced the JDK-6378256 problem ��� ���Performance problem with System.identityHashCode, compared to Object.hashCode, with client compiler.��� Simple unit test sample tried : e.g.: [ObjectHashCode.java] ---------- public class ObjectHashCode { public static void main(String[] args) { ObjectHashCode obj = new ObjectHashCode(); long time = System.nanoTime(); for(int i = 0 ; i < 1000000 ; i++) obj.hashCode(); System.out.println ("Result = " + (System.nanoTime() - time)); } } ------------ [SystemIdentityHashCode.java] ------------ public class SystemIdentityHashCode { public static void main(String[] args) { SystemIdentityHashCode obj = new SystemIdentityHashCode(); long time = System.nanoTime(); for(int i = 0 ; i < 1000000 ; i++) System.identityHashCode(obj); System.out.println ("Result = " + (System.nanoTime() - time)); } } ------------ Thanks to pointers from Tom Rodriguez, able to fix the issue locally for unit test cases when tried enabling the client-compiler-optimization that was earlier done for only for Object.hashCode, for System.identityHashCode also. (During generating native wrapper for methods, enabled support to pull the hashCode from the header word instead of doing a full VM transition) Todo / In Progress : - So far issue analysis done only for reported x86 case. To be checked for other targets. - JPRT testing - formal request for review / Webrev NOTE: Added "noreg-perf" label for this performance bug.

[~rraghavan], we think this might be a good starter bug for you once you have set up everything.

EVALUATION The optimization that's done for Object.hashCode should also be done for System.identityHashCode.