Dart VM Overview 1.0 documentation

Dart VM Advent Calendar 2012 12/08

«  Dart VM Advent Calendar 2012 12/07   ::   Contents   ::   Dart VM Advent Calendar 2012 12/09  »

Dart VM Advent Calendar 2012 12/08

Dart VMと他VMの比較

Dart VMと、他のVMやコンパイラが出力したアセンブラを比較してみようと思います。。

  • LLVM(clang3.2 trunk)
  • Dart VM
  • V8
  • JVM(java7 Hotspot)

とはいえ、比較対象はfibonacchi関数なので、実アプリケーションによるベンチマークではないです。

マイクロベンチマークでこの程度かという認識でお願いします。

Time Fibo(40)

fibo(40)の処理時間です。参考までに。

ubuntu12(ia32) corei7 2600です。

clang32$ time fibo.clang32.O3.out

ret=102334155
real  0m0.620s
user  0m0.616s
sys   0m0.000s

V8$ time shell fibo.js

ret=102334155
1401 millis
real  0m1.401s
user  0m1.404s
sys   0m0.000s

java7$ time java Fibo

ret=102334155
420 millis
real  0m0.466s
user  0m0.452s
sys   0m0.016s

なぜかClangよりも速い。。アセンブラを参照してみたら、再帰関数Fiboをinline展開していました。

そのため、以下のInline展開を抑止した版と比較します。

inline展開を抑止した場合、VM起動時のオーバーヘッドを除くと、ほぼclangと同等の速度ですね。

$ time java -XX:MaxInlineSize=0 -XX:FreqInlineSize=0 Fibo

ret = 102334155
602 millis
real  0m0.663s
user  0m0.628s
sys 0m0.036s

dart$ time dart –time-all fibo.dart

ret = 102334155
897 millis
Script Loading :  93 micros.
Snapshot Creation :  0 micros.
Isolate initialization :  11019 micros.
Function compilation :  11742 micros.
Bootstrap of core classes :  28 micros.
Total runtime for isolate :  909578 micros.
real  0m0.924s
user  0m0.920s
sys   0m0.000s

前回の最後に紹介したデータです。

clangのアセンブラ

//
//clang3.2 -O3
//

int fibo(int n) {
  if (n < 2) {
//then
    return n;
  } else {
//else
    return fibo(n-1) + fibo(n-2);
  }
}

//objdump -d -M intel
080483f0 <fibo>:
80483f0:       57                      push   edi
80483f1:       56                      push   esi
80483f2:       50                      push   eax
80483f3:       8b 74 24 10             mov    esi,DWORD PTR [esp+0x10] // esi <-- n
80483f7:       83 fe 02                cmp    esi,0x2                  // if (n < 2)
80483fa:       7d 04                   jge    8048400 <fibo+0x10>      // goto then
// else
80483fc:       89 f0                   mov    eax,esi                  // eax <-- esi
80483fe:       eb 1a                   jmp    804841a <fibo+0x2a>      // goto return
// then
8048400:       8d 46 ff                lea    eax,[esi-0x1]            // eax <-- n - 1
8048403:       89 04 24                mov    DWORD PTR [esp],eax      // push (n-1)
8048406:       e8 e5 ff ff ff          call   80483f0 <fibo>           // call fibo1
804840b:       89 c7                   mov    edi,eax                  // edi <-- ret1
804840d:       83 c6 fe                add    esi,0xfffffffe           // esi <-- n - 2
8048410:       89 34 24                mov    DWORD PTR [esp],esi      // push (n-2)
8048413:       e8 d8 ff ff ff          call   80483f0 <fibo>           // call fibo2
8048418:       01 f8                   add    eax,edi                  // eax <-- ret2 + ret1
// return
804841a:       83 c4 04                add    esp,0x4
804841d:       5e                      pop    esi
804841e:       5f                      pop    edi
804841f:       c3                      ret                             // return eax

シンプルで素直なアセンブラを出力します。これが比較のベースですね。

GCCでない理由は、VMの名前が入っていないからではなく、 GCCはfiboに対して最適化を行ってしまうため、比較対象にしていません。

Note

GCCv4.6は、fiboをループに変換し、そのループからfiboを再帰呼び出しする形に変換します。

gccv4.6でfibo(40)をコンパイルすると、400msでした。

fiboをif (n==0) ... else if (n==1) ... else の形式に変換すれば、200msになります。

V8のアセンブラ

--- Raw source ---

function fibo(n) {
  if (n < 2) {
//then
    return n;
  } else {
//else
    return fibo(n-1) + fibo(n-2);
  }
}


--- Optimized code ---
kind = OPTIMIZED_FUNCTION
name = fibo
stack_slots = 4
Instructions (size = 752)
0x27b299c0     0  55             push ebp
0x27b299c1     1  89e5           mov ebp,esp
0x27b299c3     3  56             push esi
0x27b299c4     4  57             push edi
0x27b299c5     5  83ec10         sub esp,0x10
0x27b299c8     8  c745f400000000 mov [ebp+0xf4],0x0
0x27b299cf    15  8b45fc         mov eax,[ebp+0xfc]
0x27b299d2    18  8945f0         mov [ebp+0xf0],eax
0x27b299d5    21  89c6           mov esi,eax
0x27b299d7    23  3b2530c7d908   cmp esp,[0x8d9c730]         // check stackoverflow
0x27b299dd    29  7305           jnc 36  (0x27b299e4)
0x27b299df    31  e85c5efeff     call 0x27b0f840             ;; code: STUB, StackCheckStub, minor: 0
0x27b299e4    36  8b4508         mov eax,[ebp+0x8]           // eax <-- (smi)n
0x27b299e7    39  a801           test al,0x1                 // smi check
0x27b299e9    41  0f85c0000000   jnz 239  (0x27b29aaf)       // if ! check_smi(n), goto deoptimize
0x27b299ef    47  d1f8           sar eax,1                   // (smi)n >> 1 //untag smi
0x27b299f1    49  8945ec         mov [ebp+0xec],eax          // [ebp+0xec] <- (int)n
0x27b299f4    52  83f802         cmp eax,0x2                 // if n < 2
0x27b299f7    55  0f8ca9000000   jl 230  (0x27b29aa6)        // goto else //return n
[then]
0x27b299fd    61  8b4df0         mov ecx,[ebp+0xf0]
0x27b29a00    64  8b4913         mov ecx,[ecx+0x13]
0x27b29a03    67  89c2           mov edx,eax                 // edx <-- (int)n
0x27b29a05    69  83ea01         sub edx,0x1                 // edx <-- (int)n - 1
0x27b29a08    72  8b1d1495402a   mov ebx,[0x2a409514]        ;; global property cell //property call check eq? fibo
0x27b29a0e    78  81fb05769333   cmp ebx,0x33937605          ;; object: 0x33937605 <JS Function fibo>
0x27b29a14    84  0f85f0f5e827   jnz 0x4f9b900a              ;; deoptimization bailout 1
0x27b29a1a    90  8b5917         mov ebx,[ecx+0x17]          // ebx <-- ret value //stackに返値が埋まってくるんだっけ?
0x27b29a1d    93  895df0         mov [ebp+0xf0],ebx          // このcontextのstackに入れ直し
0x27b29a20    96  53             push ebx
0x27b29a21    97  89d6           mov esi,edx                 // esi = edx = (int)(n-1)
0x27b29a23    99  03f6           add esi,esi                 // tag smi // (int)esi << 1
0x27b29a25   101  0f80b3000000   jo 286  (0x27b29ade)        // if overflow, goto deoptimize
0x27b29a2b   107  56             push esi                    // push (smi)(n-1)
0x27b29a2c   108  bf05769333     mov edi,0x33937605          ;; object: 0x33937605 <JS Function fibo>
0x27b29a31   113  8b7717         mov esi,[edi+0x17]
0x27b29a34   116  c6c102         mov_b cl,0x2
0x27b29a37   119  e884ffffff     call 0  (0x27b299c0)        ;; debug: position 72  // call fibo(n-1)
                                                             ;; code: OPTIMIZED_FUNCTION
0x27b29a3c   124  8945e8         mov [ebp+0xe8],eax          // stack ebp+0xe8 <-- (smi)fibo(n-1)の返値
0x27b29a3f   127  8b4dec         mov ecx,[ebp+0xec]          // ecx <-- (int)n
0x27b29a42   130  83e902         sub ecx,0x2                 // ecx <-- (int)n - 2
0x27b29a45   133  8b151495402a   mov edx,[0x2a409514]        ;; global property cell //property call check eq? fibo
0x27b29a4b   139  81fa05769333   cmp edx,0x33937605          ;; object: 0x33937605 <JS Function fibo>
0x27b29a51   145  0f85c7f5e827   jnz 0x4f9b901e              ;; deoptimization bailout 3
0x27b29a57   151  ff75f0         push [ebp+0xf0]
0x27b29a5a   154  03c9           add ecx,ecx                 // tag smi // (int)ecx << 1
0x27b29a5c   156  0f80e0000000   jo 386  (0x27b29b42)        // if overflow, goto deoptimize
0x27b29a62   162  51             push ecx                    // push (smi)(n-2)
0x27b29a63   163  bf05769333     mov edi,0x33937605          ;; object: 0x33937605 <JS Function fibo>
0x27b29a68   168  8b7717         mov esi,[edi+0x17]
0x27b29a6b   171  c6c102         mov_b cl,0x2
0x27b29a6e   174  e84dffffff     call 0  (0x27b299c0)        ;; debug: position 84 // call fibo(n-2)
                                                             ;; code: OPTIMIZED_FUNCTION
0x27b29a73   179  8b4de8         mov ecx,[ebp+0xe8]          // ecx <-- (smi)fibo(n-2) //stackに返値が埋まってくるんだっけ?
0x27b29a76   182  f6c101         test_b cl,0x1               // smi check(ecx)
0x27b29a79   185  0f8527010000   jnz 486  (0x27b29ba6)       // if ! check_smi, goto deoptimize
0x27b29a7f   191  d1f9           sar ecx,1                   // untag smi // (smi)fibo(n-2) >> 1
0x27b29a81   193  89c2           mov edx,eax                 // edx <-- (smi)fibo(n-1)の返値
0x27b29a83   195  f6c201         test_b dl,0x1               // smi check(edx)
0x27b29a86   198  0f8549010000   jnz 533  (0x27b29bd5)       // if ! check_smi, goto deoptimize
0x27b29a8c   204  d1fa           sar edx,1                   // untag smi,  fibo(n-1)の返値 >> 1
0x27b29a8e   206  03ca           add ecx,edx                 // ecx <-- fibo(n-1) + fibo(n-2)
0x27b29a90   208  0f809cf5e827   jo 0x4f9b9032               ;; deoptimization bailout 5 //overflow deopt
0x27b29a96   214  89c8           mov eax,ecx                 // eax <-- ecx
0x27b29a98   216  03c0           add eax,eax                 // tag smi // eax << 1
0x27b29a9a   218  0f8064010000   jo 580  (0x27b29c04)        // if overflow , goto deoptimize
0x27b29aa0   224  89ec           mov esp,ebp
0x27b29aa2   226  5d             pop ebp
0x27b29aa3   227  c20800         ret 0x8                     // return
[else]
0x27b29aa6   230  8b4508         mov eax,[ebp+0x8]           // eax <-- n
0x27b29aa9   233  89ec           mov esp,ebp
0x27b29aab   235  5d             pop ebp
0x27b29aac   236  c20800         ret 0x8                     // return n

// runtime
0x27b29aaf   239  8178ff3581b05e cmp [eax+0xff],0x5eb08135    ;; object: 0x5eb08135 <Map(elements=3)>
0x27b29ab6   246  0f8580f5e827   jnz 0x4f9b903c              ;; deoptimization bailout 6
0x27b29abc   252  f20f104003     movsd xmm0,[eax+0x3]
0x27b29ac1   257  f20f2cc0       cvttsd2si eax,xmm0
0x27b29ac5   261  f20f2ac8       cvtsi2sd xmm1,eax
0x27b29ac9   265  660f2ec1       ucomisd xmm0,xmm1
0x27b29acd   269  0f8569f5e827   jnz 0x4f9b903c              ;; deoptimization bailout 6
0x27b29ad3   275  0f8a63f5e827   jpe 0x4f9b903c              ;; deoptimization bailout 6
0x27b29ad9   281  e913ffffff     jmp 49  (0x27b299f1)
0x27b29ade   286  60             pushad
0x27b29adf   287  d1fe           sar esi,1
0x27b29ae1   289  81f600000080   xor esi,0x80000000
0x27b29ae7   295  f20f2ac6       cvtsi2sd xmm0,esi
0x27b29aeb   299  8b35e8b4d908   mov esi,[0x8d9b4e8]
0x27b29af1   305  89f0           mov eax,esi
0x27b29af3   307  83c00c         add eax,0xc
0x27b29af6   310  0f821e000000   jc 346  (0x27b29b1a)
0x27b29afc   316  3b05ecb4d908   cmp eax,[0x8d9b4ec]
0x27b29b02   322  0f8712000000   ja 346  (0x27b29b1a)
0x27b29b08   328  8905e8b4d908   mov [0x8d9b4e8],eax
0x27b29b0e   334  83c601         add esi,0x1
0x27b29b11   337  c746ff3581b05e mov [esi+0xff],0x5eb08135    ;; object: 0x5eb08135 <Map(elements=3)>
0x27b29b18   344  eb19           jmp 371  (0x27b29b33)
0x27b29b1a   346  c744240400000000 mov [esp+0x4],0x0
0x27b29b22   354  8b75fc         mov esi,[ebp+0xfc]
0x27b29b25   357  33c0           xor eax,eax
0x27b29b27   359  bb1c1d2708     mov ebx,0x8271d1c
0x27b29b2c   364  e88fdeffff     call 0x27b279c0             ;; code: STUB, CEntryStub, minor: 1
0x27b29b31   369  89c6           mov esi,eax
0x27b29b33   371  f20f114603     movsd [esi+0x3],xmm0
0x27b29b38   376  89742404       mov [esp+0x4],esi
0x27b29b3c   380  61             popad
0x27b29b3d   381  e9e9feffff     jmp 107  (0x27b29a2b)
0x27b29b42   386  60             pushad
0x27b29b43   387  d1f9           sar ecx,1
0x27b29b45   389  81f100000080   xor ecx,0x80000000
0x27b29b4b   395  f20f2ac1       cvtsi2sd xmm0,ecx
0x27b29b4f   399  8b0de8b4d908   mov ecx,[0x8d9b4e8]
0x27b29b55   405  89c8           mov eax,ecx
0x27b29b57   407  83c00c         add eax,0xc
0x27b29b5a   410  0f821e000000   jc 446  (0x27b29b7e)
0x27b29b60   416  3b05ecb4d908   cmp eax,[0x8d9b4ec]
0x27b29b66   422  0f8712000000   ja 446  (0x27b29b7e)
0x27b29b6c   428  8905e8b4d908   mov [0x8d9b4e8],eax
0x27b29b72   434  83c101         add ecx,0x1
0x27b29b75   437  c741ff3581b05e mov [ecx+0xff],0x5eb08135    ;; object: 0x5eb08135 <Map(elements=3)>
0x27b29b7c   444  eb19           jmp 471  (0x27b29b97)
0x27b29b7e   446  c744241800000000 mov [esp+0x18],0x0
0x27b29b86   454  8b75fc         mov esi,[ebp+0xfc]
0x27b29b89   457  33c0           xor eax,eax
0x27b29b8b   459  bb1c1d2708     mov ebx,0x8271d1c
0x27b29b90   464  e82bdeffff     call 0x27b279c0             ;; code: STUB, CEntryStub, minor: 1
0x27b29b95   469  89c1           mov ecx,eax
0x27b29b97   471  f20f114103     movsd [ecx+0x3],xmm0
0x27b29b9c   476  894c2418       mov [esp+0x18],ecx
0x27b29ba0   480  61             popad
0x27b29ba1   481  e9bcfeffff     jmp 162  (0x27b29a62)
0x27b29ba6   486  8179ff3581b05e cmp [ecx+0xff],0x5eb08135    ;; object: 0x5eb08135 <Map(elements=3)>
0x27b29bad   493  0f8593f4e827   jnz 0x4f9b9046              ;; deoptimization bailout 7
0x27b29bb3   499  f20f104103     movsd xmm0,[ecx+0x3]
0x27b29bb8   504  f20f2cc8       cvttsd2si ecx,xmm0
0x27b29bbc   508  f20f2ac9       cvtsi2sd xmm1,ecx
0x27b29bc0   512  660f2ec1       ucomisd xmm0,xmm1
0x27b29bc4   516  0f857cf4e827   jnz 0x4f9b9046              ;; deoptimization bailout 7
0x27b29bca   522  0f8a76f4e827   jpe 0x4f9b9046              ;; deoptimization bailout 7
0x27b29bd0   528  e9acfeffff     jmp 193  (0x27b29a81)
0x27b29bd5   533  817aff3581b05e cmp [edx+0xff],0x5eb08135    ;; object: 0x5eb08135 <Map(elements=3)>
0x27b29bdc   540  0f856ef4e827   jnz 0x4f9b9050              ;; deoptimization bailout 8
0x27b29be2   546  f20f104203     movsd xmm0,[edx+0x3]
0x27b29be7   551  f20f2cd0       cvttsd2si edx,xmm0
0x27b29beb   555  f20f2aca       cvtsi2sd xmm1,edx
0x27b29bef   559  660f2ec1       ucomisd xmm0,xmm1
0x27b29bf3   563  0f8557f4e827   jnz 0x4f9b9050              ;; deoptimization bailout 8
0x27b29bf9   569  0f8a51f4e827   jpe 0x4f9b9050              ;; deoptimization bailout 8
0x27b29bff   575  e98afeffff     jmp 206  (0x27b29a8e)
0x27b29c04   580  60             pushad
0x27b29c05   581  d1f8           sar eax,1
0x27b29c07   583  3500000080     xor eax, 0x80000000
0x27b29c0c   588  f20f2ac0       cvtsi2sd xmm0,eax
0x27b29c10   592  8b05e8b4d908   mov eax,[0x8d9b4e8]
0x27b29c16   598  89c1           mov ecx,eax
0x27b29c18   600  83c10c         add ecx,0xc
0x27b29c1b   603  0f821e000000   jc 639  (0x27b29c3f)
0x27b29c21   609  3b0decb4d908   cmp ecx,[0x8d9b4ec]
0x27b29c27   615  0f8712000000   ja 639  (0x27b29c3f)
0x27b29c2d   621  890de8b4d908   mov [0x8d9b4e8],ecx
0x27b29c33   627  83c001         add eax,0x1
0x27b29c36   630  c740ff3581b05e mov [eax+0xff],0x5eb08135    ;; object: 0x5eb08135 <Map(elements=3)>
0x27b29c3d   637  eb17           jmp 662  (0x27b29c56)
0x27b29c3f   639  c744241c00000000 mov [esp+0x1c],0x0
0x27b29c47   647  8b75fc         mov esi,[ebp+0xfc]
0x27b29c4a   650  33c0           xor eax,eax
0x27b29c4c   652  bb1c1d2708     mov ebx,0x8271d1c
0x27b29c51   657  e86addffff     call 0x27b279c0             ;; code: STUB, CEntryStub, minor: 1
0x27b29c56   662  f20f114003     movsd [eax+0x3],xmm0
0x27b29c5b   667  8944241c       mov [esp+0x1c],eax
0x27b29c5f   671  61             popad
0x27b29c60   672  e93bfeffff     jmp 224  (0x27b29aa0)
0x27b29c65   677  90             nop
0x27b29c66   678  90             nop
0x27b29c67   679  90             nop
0x27b29c68   680  90             nop
0x27b29c69   681  90             nop
0x27b29c6a   682  66             nop
0x27b29c6b   683  90             nop

頭痛くなってくる。。

Dart VMとV8を比較すると、

  • どちらも、StackOverflowCheckがある。
  • V8は、Smi型からuntagして、各種演算を行う。
  • V8は、untagした値をsmitagする際に、overflowcheckを行う。
  • Dart VMは、Smi型のまま各種演算を行っている。
  • V8は、callerのproeprty call checkを行っている。

あと予想として、Dart VMは中間表現のままRegister割付を行うため、無駄なレジスタ操作が発生していそう。。

V8はlithiumという低水準中間表現でレジスタ割付を行うため、無駄なレジスタ操作やスピルは少ないんじゃないかな。

どちらもLinear Scan Register Allocationだけど、レジスタプレッシャが大きい処理やループで傾向を比較すると分かるかもしれない。

Java7(inline展開抑止版)のアセンブラ

//Fibo.java
class Fibo {
  static int fibo(int n) {
    if (n < 2) {
      //then
      return n;
    } else {
      //else
      return fibo(n-1) + fibo(n-2);
    }
  }
  public static void main(String[] args) {
    System.out.println(fibo(40));
  }
}

$ time java -XX:MaxInlineSize=0 -XX:FreqInlineSize=0 -XX:PrintOptoAssembly Fibo

#
#  int ( int )
#
#r000 ecx   : parm 0: int                          <-- 引数n
# -- Old esp -- Framesize: 32 --                   <-- static関数なので、thisはない。
#r045 esp+28: return address                       <-- 第2引数は、edxに乗ってくる。以降はstack push
#r044 esp+24: saved fp register                    <-- method callだった場合、ecx=this, edx=arg1
#r043 esp+20: pad2, stack alignment
#r042 esp+16: Fixed slot 0
#r049 esp+12: spill
#r048 esp+ 8: spill
#r047 esp+ 4: spill
#r046 esp+ 0: spill
abababab   N1: #  B1 <- B6 B9  Freq: 1
abababab
000   B1: # B5 B2 <- BLOCK HEAD IS JUNK   Freq: 1
000     # stack bang
        PUSH   EBP  # Save EBP
        SUB    ESP, #24 # Create frame

00b     MOV    EBP,ECX                              <-- EBP = ECX = n
00d     CMP    ECX,#2                               <-- if (n < 2)
010     Jl,s  B5  P=0.500013 C=359559.000000        <-- goto then   //branchのfreqをカウントしている。
010
//else
012   B2: # B7 B3 <- B1  Freq: 0.499987
012     DEC    ECX                                  <-- ECX = (n-1)
013     CALL,static  Fibo::fibo                     <-- call fibo(n-1)
        # Fibo::fibo @ bci:10  L[0]=EBP
        # OopMap{off=24}
018
018   B3: # B8 B4 <- B2  Freq: 0.499977
        # Block is sole successor of call
018     MOV    [ESP + #0],EAX                       <-- ESP+#0 = fibo(n-1)の返値
01b     MOV    ECX,EBP                              <-- ECX = EBP = n
01d     ADD    ECX,#-2                              <-- ECX = (n-2)
        nop   # 3 bytes pad for loops and calls
023     CALL,static  Fibo::fibo                     <-- call fibo(n-2)
        # Fibo::fibo @ bci:16  L[0]=_ STK[0]=esp + #0
        # OopMap{off=40}
028
028   B4: # B6 <- B3  Freq: 0.499967
        # Block is sole successor of call
028     ADD    EAX,[ESP + #0]                       <-- ret = fibo(n-1) + fibo(n-2)
02b     JMP,s  B6                                   <-- return
02b
//then
02d   B5: # B6 <- B1  Freq: 0.500013                <-- goto if (n<2)
02d     MOV    EAX,ECX                              <-- EAX = ECX = n
02d
02f   B6: # N1 <- B5 B4  Freq: 0.99998
02f     ADD    ESP,24 # Destroy frame
        POPL   EBP
        TEST   PollPage,EAX ! Poll Safepoint

039     RET                                         <-- return EAX
039
03a   B7: # B9 <- B2  Freq: 4.99987e-06
03a     # exception oop is in EAX; no code emitted
03a     MOV    ECX,EAX
03c     JMP,s  B9
03c
03e   B8: # B9 <- B3  Freq: 4.99977e-06
03e     # exception oop is in EAX; no code emitted
03e     MOV    ECX,EAX
03e
040   B9: # N1 <- B7 B8  Freq: 9.99965e-06
040     ADD    ESP,24 # Destroy frame
        POPL   EBP

044     JMP    rethrow_stub
044



Dart VMとJava7(HotSpot)を比較すると、

  • Dart VMの引数は、すべてスタック渡し、HotSpotの引数は、第2引き数までレジスタ渡し。fastcall風。
  • HotSpotにスタックオーバーフローチェックはない?
  • HotSpotは、int型がpremitive型なので、そのままレジスタで扱える。これはHeapObjectの扱いとGCのオーバーヘッドとメモリ使用量の差を比較しないとなんともいえないけど。。
  • HotSpotは、fiboみたいな単純な関数では、DeoptimizeFrameは存在しない。クラスを使用したり、仮想関数呼び出しが必要かな。
  • HotSpotは、RETの直前に、TEST PollPage,EAX ! Poll Safepointが存在する。GC用のpollingポイントだと思うけど。。謎。
  • Dart VMにはpollingポイントの埋め込みがないけど、別途Stackmapを作成して管理しているから問題ないのかな。その辺はまだよくっってない。

Dart VMのアセンブラ

Code for optimized function 'file:///home/elise/language/dart/work/adven/fibo.dart_::_fibo' {
0xb3048308    55                     push ebp              //  v0 <- Constant:29(#null)
0xb3048309    89e5                   mov ebp,esp           //  v1 <- Parameter:30(0) {PT: dynamic} {PCid: dynamic}
0xb304830b    e800000000             call 0xb3048310
0xb3048310    83ec04                 sub esp,0x4
0xb3048313    8b4508                 mov eax,[ebp+0x8]     //  2: B1[target] ParallelMove eax <- S-1
0xb3048316    3b257c7a6b08           cmp esp,[0x86b7a7c]   //  4:     CheckStackOverflow:2()
0xb304831c    0f8668000000           jna 0xb304838a
                                                           //  8:     CheckSmi:5(v1) env={ v1 [eax], v1 [eax], v2 [C] }
0xb3048322    a801                   test al,0x1           // check SmiTag
0xb3048324    0f8573000000           jnz 0xb304839d        // goto DeoptimizeStub
                                                           //  6:     v2 <- Constant:4(#2) {PT: _Smi@0x36924d72} {PCid: _Smi@0x36924d72} [2, 2]
                                                           // 10:     Branch if RelationalOp:5(<, v1, v2 IC[1: _Smi@0x36924d72, _Smi@0x36924d72 #588]) goto (2, 3)
0xb304832a    83f804                 cmp eax,0x4           // if n < 2  // (n<<1 < 2<<1)
0xb304832d    0f8d05000000           jnl 0xb3048338        // goto B3[target]
0xb3048333    89ec                   mov esp,ebp           // 14:     Return:8(v1)
0xb3048335    5d                     pop ebp
0xb3048336    c3                     ret
0xb3048337    90                     nop                   // 16: B3[target]
                                                           // 18:     v3 <- Constant:11(#1) {PT: _Smi@0x36924d72} {PCid: _Smi@0x36924d72} [1, 1]
                                                           // 20:     ParallelMove ecx <- eax
                                                           // 20:     v4 <- BinarySmiOp:13(-, v1, v3) {PT: _Smi@0x36924d72} {PCid: _Smi@0x36924d72} [1, 1073741822] -o
0xb3048338    89c1                   mov ecx,eax
0xb304833a    83e902                 sub ecx,0x2           // n - 1  (n<<1 - 1<<1)
0xb304833d    51                     push ecx              // 22:     PushArgument:14(v4) {PCid: dynamic}
0xb304833e    bab16b0fb3             mov edx,0xb30f6bb1    // 24:     v5 <- StaticCall:15(fibo v4) {PT: dynamic} {PCid: dynamic} env={ v1 [S-1], a0 }
0xb3048343    e8c0803702             call 0xb53c0408  [stub: CallStaticFunction]  // call fibo(n-1)
0xb3048348    83c404                 add esp,0x4
0xb304834b    8b4d08                 mov ecx,[ebp+0x8]     // 26:     ParallelMove ecx <- S-1, S+0 <- eax
0xb304834e    8945f8                 mov [ebp-0x8],eax
                                                           // 26:     v7 <- BinarySmiOp:21(-, v1, v2) {PT: _Smi@0x36924d72} {PCid: _Smi@0x36924d72} [0, 1073741821] -o
0xb3048351    83e904                 sub ecx,0x4           // n - 2 (n<<1 - 2<<1)
0xb3048354    51                     push ecx              // 28:     PushArgument:22(v7) {PCid: dynamic}
0xb3048355    bab16b0fb3             mov edx,0xb30f6bb1    // 30:     v8 <- StaticCall:23(fibo v7) {PT: dynamic} {PCid: dynamic} env={ v1 [S-1], v5 [S+0], a0 }
0xb304835a    e8a9803702             call 0xb53c0408  [stub: CallStaticFunction]  // call fibo(n-2)
0xb304835f    83c404                 add esp,0x4
0xb3048362    89c1                   mov ecx,eax           // 31:     ParallelMove ecx <- eax, eax <- S+0
0xb3048364    8b45f8                 mov eax,[ebp-0x8]
                                                           // 32:     CheckSmi:25(v5) env={ v1 [S-1], v5 [eax], v8 [ecx] }
0xb3048367    a801                   test al,0x1           // check SmiTag
0xb3048369    0f8533000000           jnz 0xb30483a2        // goto DeoptimizeStub
                                                           // 34:     CheckSmi:25(v8) env={ v1 [S-1], v5 [eax], v8 [ecx] }
0xb304836f    f6c101                 test_b ecx,0x1        // check SmiTag
0xb3048372    0f852f000000           jnz 0xb30483a7        // goto DeoptimizeStub
0xb3048378    89c2                   mov edx,eax           // 36:     ParallelMove edx <- eax
                                                           // 36:     v9 <- BinarySmiOp:25(+, v5, v8) {PT: _Smi@0x36924d72} {PCid: _Smi@0x36924d72} [-inf, +inf] +o env={ v1 [S-1], v5 [eax], v8 [ecx] }
0xb304837a    03d1                   add edx,ecx           // fibo(n-1) + fibo(n-2)
0xb304837c    0f802a000000           jo 0xb30483ac
0xb3048382    89d0                   mov eax,edx           // 37:     ParallelMove eax <- edx
0xb3048384    89ec                   mov esp,ebp           // 38:     Return:26(v9)
0xb3048386    5d                     pop ebp
0xb3048387    c3                     ret
//Runtime
0xb3048388    90                     nop
0xb3048389    cc                     int3
0xb304838a    50                     push eax
0xb304838b    b9f0c20a08             mov ecx,0x80ac2f0
0xb3048390    ba00000000             mov edx,0
0xb3048395    e88e7c3702             call 0xb53c0028  [stub: CallToRuntime]
0xb304839a    58                     pop eax
0xb304839b    eb85                   jmp 0xb3048322
0xb304839d    e8c6813702             call 0xb53c0568  [stub: Deoptimize]
0xb30483a2    e8c1813702             call 0xb53c0568  [stub: Deoptimize]
0xb30483a7    e8bc813702             call 0xb53c0568  [stub: Deoptimize]
0xb30483ac    e8b7813702             call 0xb53c0568  [stub: Deoptimize]
0xb30483b1    e972813702             jmp 0xb53c0528  [stub: FixCallersTarget]
0xb30483b6    e94d823702             jmp 0xb53c0608  [stub: DeoptimizeLazy]
}



まとめ

  1. HotSpotやばい。C言語と性能競争の話題がでるだけはある。
  2. V8はもうちょっとなんとかならないんですかね。。

«  Dart VM Advent Calendar 2012 12/07   ::   Contents   ::   Dart VM Advent Calendar 2012 12/09  »