> but the optimized code only appears to be checking the stack limit at
> the function entry, not in the loop itself.

Yes. As I said in my previous email: optimizing compiler eliminates
stack checks that are dominated by calls because called functions
should at least have a stack check in the prologue.

However there seems to be a minor issue here. Apparently HandleApiCall
builtin does not perform any stack checks thus breaking
HStackCheckEliminator assumption that every call implies a stack
check.

If print in your example is a JS function everything is fine because
JS function has a stack check in the prologue. But if print is an API
function then this loop will have no interruption point which is bad.

--
Vyacheslav Egorov


On Wed, Aug 31, 2011 at 10:39 PM, Kyle Morgan <[email protected]> wrote:
> Hi Vyacheslav,
>
> Allow me to demonstrate what I mean.  I ran the v8 shell with code
> containing the following function.
>
> function loop() {
>   for(var i = 0; i < 5; ++i) {
>     print(i);
>   }
> }
>
> It appears to be emitting the following code (optimized and unoptimized).
>
> --- Code ---
> kind = FUNCTION
> name = loop
> Instructions (size = 196)
> 0x7f6f3e26fca0     0  55             push rbp
> 0x7f6f3e26fca1     1  4889e5         REX.W movq rbp,rsp
> 0x7f6f3e26fca4     4  56             push rsi
> 0x7f6f3e26fca5     5  57             push rdi
> 0x7f6f3e26fca6     6  41ff7598       push [r13-0x68]
> 0x7f6f3e26fcaa    10  493b6508       REX.W cmpq rsp,[r13+0x8]
> 0x7f6f3e26fcae    14  7305           jnc 21  (0x7f6f3e26fcb5)
> 0x7f6f3e26fcb0    16  e82bf4fdff     call 0x7f6f3e24f0e0     ;; debug:
> statement 36
>                                                             ;; code: STUB,
> StackCheckStub, minor: 0
> 0x7f6f3e26fcb5    21  33c0           xorl rax,rax
> 0x7f6f3e26fcb7    23  488945e8       REX.W movq [rbp-0x18],rax
> 0x7f6f3e26fcbb    27  e94d000000     jmp 109  (0x7f6f3e26fd0d)
> 0x7f6f3e26fcc0    32  ff7627         push [rsi+0x27]
> 0x7f6f3e26fcc3    35  ff75e8         push [rbp-0x18]
> 0x7f6f3e26fcc6    38  48b9919790636f7f0000 REX.W movq rcx,0x7f6f63909791
>  ;; object: 0x7f6f63909791 <String[5]: print>
> 0x7f6f3e26fcd0    48  e80b98ffff     call 0x7f6f3e2694e0     ;; debug:
> statement 76
>                                                             ;; code:
> contextual, CALL_IC, UNINITIALIZED, in_loop, argc = 1
> 0x7f6f3e26fcd5    53  488b75f8       REX.W movq rsi,[rbp-0x8]
> 0x7f6f3e26fcd9    57  488b45e8       REX.W movq rax,[rbp-0x18]
> 0x7f6f3e26fcdd    61  a801           test al,0x1
> 0x7f6f3e26fcdf    63  7405           jz 70  (0x7f6f3e26fce6)
> 0x7f6f3e26fce1    65  e89a83feff     call 0x7f6f3e258080     ;; debug:
> statement 43
>                                                             ;; debug:
> position 67
>                                                             ;; code: STUB,
> ToNumberStub, minor: 0
> 0x7f6f3e26fce6    70  4c01e0         REX.W addq rax,r12
> 0x7f6f3e26fce9    73  7004           jo 79  (0x7f6f3e26fcef)
> 0x7f6f3e26fceb    75  a801           test al,0x1
> 0x7f6f3e26fced    77  720d           jc 92  (0x7f6f3e26fcfc)
> 0x7f6f3e26fcef    79  4c29e0         REX.W subq rax,r12
> 0x7f6f3e26fcf2    82  4c89e2         REX.W movq rdx,r12
> 0x7f6f3e26fcf5    85  e80658feff     call 0x7f6f3e255500     ;; code:
> BINARY_OP_IC, UNINITIALIZED (id = 30)
> 0x7f6f3e26fcfa    90  a80d           test al,0xd
> 0x7f6f3e26fcfc    92  488945e8       REX.W movq [rbp-0x18],rax
> 0x7f6f3e26fd00    96  493b6508       REX.W cmpq rsp,[r13+0x8]
> 0x7f6f3e26fd04   100  7307           jnc 109  (0x7f6f3e26fd0d)
> 0x7f6f3e26fd06   102  e8d5f3fdff     call 0x7f6f3e24f0e0     ;; code: STUB,
> StackCheckStub, minor: 0
> 0x7f6f3e26fd0b   107  a801           test al,0x1
> 0x7f6f3e26fd0d   109  ff75e8         push [rbp-0x18]
> 0x7f6f3e26fd10   112  4b8d04a4       REX.W leaq rax,[r12+r12*4]
> 0x7f6f3e26fd14   116  5a             pop rdx
> 0x7f6f3e26fd15   117  488bca         REX.W movq rcx,rdx
> 0x7f6f3e26fd18   120  480bc8         REX.W orq rcx,rax
> 0x7f6f3e26fd1b   123  f6c101         testb rcx,0x1
> 0x7f6f3e26fd1e   126  730a           jnc 138  (0x7f6f3e26fd2a)
> 0x7f6f3e26fd20   128  483bd0         REX.W cmpq rdx,rax
> 0x7f6f3e26fd23   131  7c9b           jl 32  (0x7f6f3e26fcc0)
> 0x7f6f3e26fd25   133  e91d000000     jmp 167  (0x7f6f3e26fd47)
> 0x7f6f3e26fd2a   138  e8313cfeff     call 0x7f6f3e253960     ;; debug:
> position 60
>                                                             ;; code:
> COMPARE_IC, UNINITIALIZED (id = 23)
> 0x7f6f3e26fd2f   143  a811           test al,0x11
> 0x7f6f3e26fd31   145  eb0b           jmp 158  (0x7f6f3e26fd3e)
> 0x7f6f3e26fd33   147  493b45b0       REX.W cmpq rax,[r13-0x50]
> 0x7f6f3e26fd37   151  7487           jz 32  (0x7f6f3e26fcc0)
> 0x7f6f3e26fd39   153  e909000000     jmp 167  (0x7f6f3e26fd47)
> 0x7f6f3e26fd3e   158  4885c0         REX.W testq rax,rax
> 0x7f6f3e26fd41   161  0f8c79ffffff   jl 32  (0x7f6f3e26fcc0)
> 0x7f6f3e26fd47   167  498b4598       REX.W movq rax,[r13-0x68]
> 0x7f6f3e26fd4b   171  488be5         REX.W movq rsp,rbp      ;; debug:
> statement 90
>                                                             ;; js return
> 0x7f6f3e26fd4e   174  5d             pop rbp
> 0x7f6f3e26fd4f   175  c20800         ret 0x8
> 0x7f6f3e26fd52   178  cc             int3
> 0x7f6f3e26fd53   179  cc             int3
> 0x7f6f3e26fd54   180  cc             int3
> 0x7f6f3e26fd55   181  cc             int3
> 0x7f6f3e26fd56   182  cc             int3
> 0x7f6f3e26fd57   183  cc             int3
>
> --- Optimized code ---
> kind = OPTIMIZED_FUNCTION
> name = loop
> stack_slots = 2
> Instructions (size = 234)
> 0x7f6f3e2703a0     0  55             push rbp
> 0x7f6f3e2703a1     1  4889e5         REX.W movq rbp,rsp
> 0x7f6f3e2703a4     4  56             push rsi
> 0x7f6f3e2703a5     5  57             push rdi
> 0x7f6f3e2703a6     6  4883ec10       REX.W subq rsp,0x10
> 0x7f6f3e2703aa    10  488bc6         REX.W movq rax,rsi
> 0x7f6f3e2703ad    13  493b6508       REX.W cmpq rsp,[r13+0x8]
> 0x7f6f3e2703b1    17  7305           jnc 24  (0x7f6f3e2703b8)
> 0x7f6f3e2703b3    19  e828edfdff     call 0x7f6f3e24f0e0     ;; code: STUB,
> StackCheckStub, minor: 0
> 0x7f6f3e2703b8    24  488b4627       REX.W movq rax,[rsi+0x27]
> 0x7f6f3e2703bc    28  488b4027       REX.W movq rax,[rax+0x27]
> 0x7f6f3e2703c0    32  488945e8       REX.W movq [rbp-0x18],rax
> 0x7f6f3e2703c4    36  bb00000000     movl rbx,(nil)
> 0x7f6f3e2703c9    41  48895de0       REX.W movq [rbp-0x20],rbx
> 0x7f6f3e2703cd    45  83fb05         cmpl rbx,0x5
> 0x7f6f3e2703d0    48  0f8d5c000000   jge 146  (0x7f6f3e270432)
> 0x7f6f3e2703d6    54  48ba881d7f636f7f0000 REX.W movq rdx,0x7f6f637f1d88
>  ;; global property cell
> 0x7f6f3e2703e0    64  488b12         REX.W movq rdx,[rdx]
> 0x7f6f3e2703e3    67  493b55a0       REX.W cmpq rdx,[r13-0x60]
> 0x7f6f3e2703e7    71  0f8456000000   jz 163  (0x7f6f3e270443)
> 0x7f6f3e2703ed    77  49ba719295636f7f0000 REX.W movq r10,0x7f6f63959271
>  ;; object: 0x7f6f63959271 <JS Function print>
> 0x7f6f3e2703f7    87  493bd2         REX.W cmpq rdx,r10
> 0x7f6f3e2703fa    90  0f8550000000   jnz 176  (0x7f6f3e270450)
> 0x7f6f3e270400    96  50             push rax
> 0x7f6f3e270401    97  488bd3         REX.W movq rdx,rbx
> 0x7f6f3e270404   100  48c1e220       REX.W shlq rdx,32
> 0x7f6f3e270408   104  52             push rdx
> 0x7f6f3e270409   105  48bf719295636f7f0000 REX.W movq rdi,0x7f6f63959271
>  ;; object: 0x7f6f63959271 <JS Function print>
> 0x7f6f3e270413   115  b801000000     movl rax,0x1
> 0x7f6f3e270418   120  4c89e1         REX.W movq rcx,r12
> 0x7f6f3e27041b   123  ff5717         call [rdi+0x17]         ;; debug:
> position 76
> 0x7f6f3e27041e   126  488b75f8       REX.W movq rsi,[rbp-0x8]
> 0x7f6f3e270422   130  488b45e0       REX.W movq rax,[rbp-0x20]
> 0x7f6f3e270426   134  83c001         addl rax,0x1
> 0x7f6f3e270429   137  488bd8         REX.W movq rbx,rax
> 0x7f6f3e27042c   140  488b45e8       REX.W movq rax,[rbp-0x18]
> 0x7f6f3e270430   144  eb97           jmp 41  (0x7f6f3e2703c9)
> 0x7f6f3e270432   146  48b8b1208f636f7f0000 REX.W movq rax,0x7f6f638f20b1
>  ;; object: 0x7f6f638f20b1 <undefined>
> 0x7f6f3e27043c   156  488be5         REX.W movq rsp,rbp
> 0x7f6f3e27043f   159  5d             pop rbp
> 0x7f6f3e270440   160  c20800         ret 0x8
> 0x7f6f3e270443   163  49ba4aa0283e6f7f0000 REX.W movq r10,0x7f6f3e28a04a
>  ;; deoptimization bailout 1
> 0x7f6f3e27044d   173  41ffe2         jmp r10
> 0x7f6f3e270450   176  49ba54a0283e6f7f0000 REX.W movq r10,0x7f6f3e28a054
>  ;; deoptimization bailout 2
> 0x7f6f3e27045a   186  41ffe2         jmp r10
> 0x7f6f3e27045d   189  90             nop
> 0x7f6f3e27045e   190  90             nop
> 0x7f6f3e27045f   191  90             nop
> 0x7f6f3e270460   192  90             nop
> 0x7f6f3e270461   193  90             nop
> 0x7f6f3e270462   194  90             nop
> 0x7f6f3e270463   195  90             nop
> 0x7f6f3e270464   196  90             nop
> 0x7f6f3e270465   197  90             nop
> 0x7f6f3e270466   198  90             nop
> 0x7f6f3e270467   199  90             nop
> 0x7f6f3e270468   200  90             nop
> 0x7f6f3e270469   201  90             nop
> 0x7f6f3e27046a   202  6690           nop
>
> It appears that the unoptimized code is emitting two stack limit checks.
>  One at offset 16 at the function entry (but prior to the loop starting at
> offset 32), and another at offset 102, prior to the loop's backward jump.
>  However, the optimized code is only emitting one stack check at offset 19,
> when the loop doesn't appear to start until offset 41.  Correct me if I'm
> wrong, but the optimized code only appears to be checking the stack limit at
> the function entry, not in the loop itself.
>
> - Kyle
>
>
>
> On Wed, Aug 31, 2011 at 3:53 PM, Vyacheslav Egorov <[email protected]>
> wrote:
>> Hi Kyle,
>>
>> Optimizing compiler inserts stack checks (HStackCheck instruction)
>> explicitly at loop body's entry[1].
>>
>> It also does an optimization pass[2] to remove redundant stack checks
>> that are dominated by function calls (as functions always does stack
>> check in the prologue).
>>
>> Stack checks are important part of V8's interruption mechanism so both
>> compilers emit them to make all loops interruptable.
>>
>> [1] http://code.google.com/p/v8/source/browse/trunk/src/hydrogen.cc#2823
>> [2] http://code.google.com/p/v8/source/browse/trunk/src/hydrogen.cc#1247
>>
>> --
>> Vyacheslav Egorov
>>
>>
>> On Wed, Aug 31, 2011 at 9:27 PM, Kyle <[email protected]> wrote:
>>> Hello,
>>>
>>> Some time ago I noticed that the v8 compile was inserting stack limit
>>> checks at the back edges of loops.  I later found out that this check
>>> was doubling as a preemption mechanism to interrupt potentially long-
>>> running code.  However, I've noticed that the hydrogen/lithium
>>> compiler included with crankshaft does not seem to include these
>>> checks.  Is there a particular reason for this?  Is the previous
>>> design for JavaScript preemption no longer being pursued?
>>>
>>> --
>>> v8-users mailing list
>>> [email protected]
>>> http://groups.google.com/group/v8-users
>>>
>>
>> --
>> v8-users mailing list
>> [email protected]
>> http://groups.google.com/group/v8-users
>
> --
> v8-users mailing list
> [email protected]
> http://groups.google.com/group/v8-users

-- 
v8-users mailing list
[email protected]
http://groups.google.com/group/v8-users

Reply via email to