Hi Vladimir,

Why do you need getHistoricInt ?
Is it because Unsafe.getInt() doesn't do any constant folding ?

BTW, why getHistoricInt is named getHistoricInt ?

cheers,
RĂ©mi

On 10/10/2014 09:08 PM, Vladimir Ivanov wrote:
http://cr.openjdk.java.net/~vlivanov/8059877/webrev.00/
https://bugs.openjdk.java.net/browse/JDK-8059877

LambdaForm sharing introduces profile pollution in compiled LambdaForms. The most serious consequence is inlining distortion, which severely degrade peak performance. The main victim is guardWithTest (GWT) combinator.

Before LambdaForm sharing, inlining in GWT was affected by 2 aspects:
  - branch frequencies: never-taken branch is skipped;
- target & fallback method handles (corresponding LFs: compiled vs interpreted): if method handle has been invoked < COMPILE_THRESHOLD times, LambdaForm.vmentry points to LF interpreter which is marked w/ @DontInline.

LambdaForm sharing breaks both aspects:
  - sharing of GWT LambdaForm pollutes branch profile;
- sharing of LambdaForms used in target & fallback pollutes invocation counters.

I experimented w/ VM API to guide JIT-compiler using profiling information gathered on LambdaForm level [1], but decided to take safer route for now (8u40). JIT-compiler control approach looks promising, but I need more time to get rid of some performance artifacts it suffers from.

The proposed fix is to mimic behavior of fully customized LambdaForms.
When GWT is created, both target & fallback method handles are wrapped in a special reinoker, which blocks inlining (@DontInline on reinvoker's compiled LambdaForm). Once a wrapper is invoked more that DONT_INLINE_THRESHOLD times, it's LambdaForm is replaced with a regular reinvoker, which is fully transparent for the JIT and it inlines smoothly.

The downside of the chosen approach is that LambdaForm.updateForm() doesn't guarantee that all places where stale LambaForm is used see the update. If it is already part of some nmethod, it won't be invalidated and recompiled, but will be kept as is. It shouldn't be a problem, since DONT_INLINE_THRESHOLD is expected to be pretty low (~30), so only very rarely executed branches are affected.

The fix significantly improves peak performance w/ full LF sharing (USE_LF_EDITOR=true).

Octane/nashorn results [2] for:
  (1) USE_LF_EDITOR=false DONT_INLINE_THRESHOLD=0 (default for 8u40&9)
  (2) USE_LF_EDITOR=true  DONT_INLINE_THRESHOLD=0 (default for 8u40&9)
  (3) USE_LF_EDITOR=true  DONT_INLINE_THRESHOLD=30 (fixed version)

(1) & (2) correspond to default configurations (partial & full LF sharing respectively). (3) is the fixed version.

The fix recovers peak performance for:
 * Crypto:       ~255ms -> ~12ms;
 * DeltaBlue:     ~40ms ->  ~2ms;
 * Raytracer:     ~62ms ->  ~7ms;
 * EarleyBoyer:  ~160ms ->  ~22ms;
 * NavierStokes:  ~17ms ->  ~13ms;

2 subbenchmarks (Box2D & Gbemu) still has some regressions, but it's much better now:
   Box2D: ~48ms -> ~61ms  (w/o the fix: ~155ms)
   Gbemu: ~88ms -> ~116ms (w/o the fix: ~160ms)

Testing:
tests: jck (api/java_lang/invoke), jdk/java/lang/invoke, jdk/java/util/streams, octane
 configurations: -ea -esa -Xverify:all
+ COMPILE_THRESHOLD={0,30} + USE_LF_EDITOR={false,true} + DONT_INLINE_THRESHOLD={0,30}

Thanks!

Best regards,
Vladimir Ivanov

[1] http://cr.openjdk.java.net/~vlivanov/profiling/
[2] http://cr.openjdk.java.net/~vlivanov/8059877/octane.txt
_______________________________________________
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

_______________________________________________
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

Reply via email to