-
Enhancement
-
Resolution: Fixed
-
P4
-
None
-
b04
Around 6% of bytecode executed bootstrapping ISC is spent in IBG::getInternalName and, via calls in IBG to get method and field descriptors, in BytecodeDescriptor::unparse. These calls create various short-lived String objects.
For the case of unparsing fields and methods, we can observe that almost all calls with a non-primitive type is Object.class, and almost all primitives are int.class. Special-casing "Ljava/lang/Object;" turns out to be very profitable generally, and special-casing int.class is profitable in unparse(Class<?>)
For the case of IBG::getInternalName, it turns out that it's often getting the internal name of the species type that is cause of String creation (Object.class etc are already special cases), and we generate the same String at least 4 times. Adding a tiny IBG instance-level map to act as a short-lived cache drops getInternalName overhead by ~80%
For the case of unparsing fields and methods, we can observe that almost all calls with a non-primitive type is Object.class, and almost all primitives are int.class. Special-casing "Ljava/lang/Object;" turns out to be very profitable generally, and special-casing int.class is profitable in unparse(Class<?>)
For the case of IBG::getInternalName, it turns out that it's often getting the internal name of the species type that is cause of String creation (Object.class etc are already special cases), and we generate the same String at least 4 times. Adding a tiny IBG instance-level map to act as a short-lived cache drops getInternalName overhead by ~80%