2017-07-28 11 views
3

Javaループから生成されたネイティブコードを理解しようとしています。ネイティブコードはC2コンパイラによって最適化する必要がありますが、私の簡単な例では最適化されていないようです。C2 JITコンパイラによってJavaループの述語の最適化がトリガされるのはいつですか?

これは私がhttps://wiki.openjdk.java.net/display/HotSpot/LoopPredicationの最小限の例でベースを書いたJavaメソッドです:

104 public static byte[] myLoop(int init, int limit, int stride, int scale, int offset, byte value, byte[] array) { 
105  for (int i = init; i < limit; i += stride) { 
106   array [ scale * i + offset] = value; 
107  } 
108  return array; 
109 } 

これらは、C2のコンパイルを強制するには、Java 8のホットスポットVMに与えられた引数です:

-server 
-XX:-TieredCompilation 
-XX:CompileThreshold=5 
-XX:+UnlockDiagnosticVMOptions 
-XX:+PrintAssembly 
-XX:-UseCompressedOops 
-XX:+LogCompilation 
-XX:+TraceClassLoading 
-XX:+UseLoopPredicate 
-XX:+RangeCheckElimination 

これをC2によって生成されたamd64ネイティブコードです( 'myLoop'は少なくとも10000回呼び出されます)。

# {method} {0x00007fcb5088ef38} 'myLoop' '(IIIIIB[B)[B' in 'MyClass'                                                                      
    # parm0: rsi  = int 
    # parm1: rdx  = int 
    # parm2: rcx  = int 
    # parm3: r8  = int 
    # parm4: r9  = int 
    # parm5: rdi  = byte 
    # parm6: [sp+0x40] = '[B' (sp of caller) 
    0x00007fcd44ee9fe0: mov  %eax,0xfffffffffffec000(%rsp) 
    0x00007fcd44ee9fe7: push %rbp 
    0x00007fcd44ee9fe8: sub  $0x30,%rsp  ;*synchronization entry 
               ; - MyClass::[email protected] (line 105) 

    0x00007fcd44ee9fec: cmp  %edx,%esi 
    0x00007fcd44ee9fee: jnl  0x7fcd44eea04a ;*if_icmplt 
               ; - MyClass::[email protected] (line 105) 

    0x00007fcd44ee9ff0: mov  0x40(%rsp),%rax 
    0x00007fcd44ee9ff5: mov  0x10(%rax),%r10d ;*bastore 
               ; - MyClass::[email protected] (line 106) 
               ; implicit exception: dispatches to 0x00007fcd44eea051 
    0x00007fcd44ee9ff9: nopl 0x0(%rax)   ;*aload 
               ; - MyClass::[email protected] (line 106) 

    0x00007fcd44eea000: mov  %esi,%ebx 
    0x00007fcd44eea002: imull %r8d,%ebx 
    0x00007fcd44eea006: add  %r9d,%ebx   ;*iadd 
               ; - MyClass::[email protected] (line 106) 

    0x00007fcd44eea009: cmp  %r10d,%ebx 
    0x00007fcd44eea00c: jnb  0x7fcd44eea02e ;*bastore 
               ; - MyClass::[email protected] (line 106) 

    0x00007fcd44eea00e: add  %ecx,%esi   ;*iadd 
               ; - MyClass::[email protected] (line 105) 

    0x00007fcd44eea010: movsxd %ebx,%r11 
    0x00007fcd44eea013: mov  %dil,0x18(%rax,%r11) ; OopMap{rax=Oop off=56} 
               ;*if_icmplt 
               ; - MyClass::[email protected] (line 105) 

    0x00007fcd44eea018: test %eax,0xa025fe2(%rip) ; {poll} 
    0x00007fcd44eea01e: cmp  %edx,%esi 
    0x00007fcd44eea020: jl  0x7fcd44eea000 ;*synchronization entry 
               ; - MyClass::[email protected] (line 105) 

    0x00007fcd44eea022: add  $0x30,%rsp 
    0x00007fcd44eea026: pop  %rbp 
    0x00007fcd44eea027: test %eax,0xa025fd3(%rip) ; {poll_return} 
    0x00007fcd44eea02d: retq 
    0x00007fcd44eea02e: movabs $0x7fcca3c810a8,%rsi ; {oop(a 'java/lang/ArrayIndexOutOfBoundsException')} 
    0x00007fcd44eea038: movq $0x0,0x18(%rsi) ;*bastore 
               ; - MyClass::[email protected] (line 106) 

    0x00007fcd44eea040: add  $0x30,%rsp 
    0x00007fcd44eea044: pop  %rbp 
    0x00007fcd44eea045: jmpq 0x7fcd44e529a0 ; {runtime_call} 
    0x00007fcd44eea04a: mov  0x40(%rsp),%rax 
    0x00007fcd44eea04f: jmp  0x7fcd44eea022 
    0x00007fcd44eea051: mov  %edx,%ebp 
    0x00007fcd44eea053: mov  %ecx,0x40(%rsp) 
    0x00007fcd44eea057: mov  %r8d,0x44(%rsp) 
    0x00007fcd44eea05c: mov  %r9d,(%rsp) 
    0x00007fcd44eea060: mov  %edi,0x4(%rsp) 
    0x00007fcd44eea064: mov  %rax,0x8(%rsp) 
    0x00007fcd44eea069: mov  %esi,0x10(%rsp) 
    0x00007fcd44eea06d: mov  $0xffffff86,%esi 
    0x00007fcd44eea072: nop 
    0x00007fcd44eea073: callq 0x7fcd44dea1a0 ; OopMap{[8]=Oop off=152} 
               ;*aload 
               ; - MyClass::[email protected] (line 106) 
               ; {runtime_call} 
    0x00007fcd44eea078: callq 0x7fcd4dc47c50 ;*aload 
               ; - MyClass::[email protected] (line 106) 
               ; {runtime_call} 
    0x00007fcd44eea07d: hlt 
    0x00007fcd44eea07e: hlt 
    0x00007fcd44eea07f: hlt 

https://wiki.openjdk.java.net/display/HotSpot/LoopPredicationによれば、「配列範囲の除去」と呼ばれる最適化の1つでは、ループ内の配列範囲のチェックは不要ですが、ループの前にループ述語が追加されます。この最適化はC2による 'myLoop'では行われていないようです。ループの逆方向ジャンプは0x7fcd44eea020にあり、0x7fcd44eea000にジャンプします。ループ内では、依然として範囲チェックが0x7fcd44eea009-0x7fcd44eea00cにあります。

  1. なぜループ内にまだチェックがありますか?
  2. ループの最適化の最適化が実行されていないのはなぜですか?
  3. どのようにすべての最適化を強制することができますか?説明は、same page右ある

答えて

3

:配列範囲チェック除去用ループ叙述 を実行するために、上記の例から

、要件はinitlimitoffsetarrayアールそのループ不変量であり、stridescaleはコンパイル時には の定数です。あなたの例scalestride

時定数をコンパイルするので、最適化は失敗していません。

しかし、このメソッドを定数引数で呼び出すと、HotSpotはインライン化と定数伝​​播の最適化による範囲チェックをなくすことができます。

+1

また、 'UseLoopPredicate'と' RangeCheckElimination'フラグを指定する必要はありません。これらはデフォルトで有効になっています。 – apangin

関連する問題