• Benedikt Meurer's avatar
    [turbofan] ReceiverOrNullOrUndefined feedback for JSEqual. · f19c4a59
    Benedikt Meurer authored
    This changes the ReceiverOrOddball feedback on JSStrictEqual to
    ReceiverOrNullOrUndefined feedback, which can also safely be
    consumed by JSEqual (we cannot generally accept any oddball here
    since booleans trigger implicit conversions, unfortunately).
    Thus we replace the previously introduced CheckReceiverOrOddball
    with CheckReceiverOrNullOrUndefined, and drop CheckOddball, since
    we will no longer collect Oddball feedback separately.
    
    TurboFan will then turn a JSEqual[ReceiverOrNullOrUndefined] into
    a sequence like this:
    
    ```
    left = CheckReceiverOrNullOrUndefined(left);
    right = CheckReceiverOrNullOrUndefined(right);
    result = if ObjectIsUndetectable(left) then
               ObjectIsUndetectable(right)
             else
               ReferenceEqual(left, right);
    ```
    
    This significantly improves the peak performance of abstract equality
    with Receiver, Null or Undefined inputs. On the test case outlined in
    http://crbug.com/v8/8356 we go from
    
      naive: 2946 ms.
      tenary: 2134 ms.
    
    to
    
      naive: 2230 ms.
      tenary: 2250 ms.
    
    which corresponds to a 25% improvement on the abstract equality case.
    For regular code this will probably yield more performance, since we
    get rid of the JSEqual operator, which might have arbitrary side
    effects and thus blocks all kinds of TurboFan optimizations. The
    JSStrictEqual case is slightly slower now, since it has to rule out
    booleans as well (even though that's not strictly necessary, but
    consistency is key here).
    
    This way developers can safely use `a == b` instead of doing a dance
    like `a == null ? b == null : a === b` (which is what dart2js does
    right now) when both `a` and `b` are known to be Receiver, Null or
    Undefined. The abstract equality is not only faster to parse than
    the tenary, but also generates a shorter bytecode sequence. In the
    test case referenced in http://crbug.com/v8/8356 the bytecode for
    `naive` is
    
    ```
    StackCheck
    Ldar a1
    TestEqual a0, [0]
    JumpIfFalse [5]
    LdaSmi [1]
    Return
    LdaSmi [2]
    Return
    ```
    
    which is 14 bytes, whereas the `tenary` function generates
    
    ```
    StackCheck
    Ldar a0
    TestUndetectable
    JumpIfFalse [7]
    Ldar a1
    TestUndetectable
    Jump [7]
    Ldar a1
    TestEqualStrict a0, [0]
    JumpIfToBooleanFalse [5]
    LdaSmi [1]
    Return
    LdaSmi [2]
    Return
    ```
    
    which is 24 bytes. So the `naive` version is 40% smaller and requires
    fewer bytecode dispatches.
    
    Bug: chromium:898455, v8:8356
    Change-Id: If3961b2518b4438700706b3bd6071d546305e233
    Reviewed-on: https://chromium-review.googlesource.com/c/1297315Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
    Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
    Cr-Commit-Position: refs/heads/master@{#56948}
    f19c4a59
js-graph.cc 6.83 KB