-
Bug
-
Resolution: Fixed
-
P3
-
None
-
b131
-
Not verified
@CallerSensitive methods typically contain a call to Reflection.getCallerClass, which goes into JVM_GetCallerClass. During JVM_GetCallerClass the stack has this form:
// Getting the class of the caller frame.
//
// The call stack at this point looks something like this:
//
// [0] [ @CallerSensitive public sun.reflect.Reflection.getCallerClass ]
// [1] [ @CallerSensitive API.method ]
// [.] [ (skipped intermediate frames) ]
// [n] [ caller ]
C2 exploits this by intrinsifying Reflection.getCallerClass. If the inline is deep enough, then a frame with a caller is known already, and we can short-cut the stack walk.
In microbenchmarks testing things like access control, failing to inline @CS methods such as Method.invoke can drastically reduce performance by an order of magnitude, making performance characteristics very brittle.
In the context of jigsaw, where access checks have been changing to account for modules - and inlining behavior with it - various benchmarks are now bouncing back and forth between a good state where everything is inlined and fast, and a bad state where Reflection.getCallerClass is not inlined and intrinsified - both from build to build but also from run to run.
Force inlining Method.invoke, Field.get* etc stabilize all such benchmarks at the better level, and we can likely benefit from applying this to most @CallerSensitive methods, unless they're obviously not performance critical.
One grey area are methods marked @CallerSensitive but which call Reflection.getCallerClass() iff there is a SecurityManager installed. For less performance surprises when running with a SecurityManager it might make sense to make the @ForceInline as well.
// Getting the class of the caller frame.
//
// The call stack at this point looks something like this:
//
// [0] [ @CallerSensitive public sun.reflect.Reflection.getCallerClass ]
// [1] [ @CallerSensitive API.method ]
// [.] [ (skipped intermediate frames) ]
// [n] [ caller ]
C2 exploits this by intrinsifying Reflection.getCallerClass. If the inline is deep enough, then a frame with a caller is known already, and we can short-cut the stack walk.
In microbenchmarks testing things like access control, failing to inline @CS methods such as Method.invoke can drastically reduce performance by an order of magnitude, making performance characteristics very brittle.
In the context of jigsaw, where access checks have been changing to account for modules - and inlining behavior with it - various benchmarks are now bouncing back and forth between a good state where everything is inlined and fast, and a bad state where Reflection.getCallerClass is not inlined and intrinsified - both from build to build but also from run to run.
Force inlining Method.invoke, Field.get* etc stabilize all such benchmarks at the better level, and we can likely benefit from applying this to most @CallerSensitive methods, unless they're obviously not performance critical.
One grey area are methods marked @CallerSensitive but which call Reflection.getCallerClass() iff there is a SecurityManager installed. For less performance surprises when running with a SecurityManager it might make sense to make the @ForceInline as well.
- relates to
-
JDK-8037325 Class.getConstructor() performance regression
-
- Closed
-