1. 07 May, 2020 1 commit
  2. 04 Mar, 2019 1 commit
  3. 24 Oct, 2018 1 commit
    • 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