Bug 199967 - Micro-optimize HashMap & String IPC decoding
Summary: Micro-optimize HashMap & String IPC decoding
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKit2 (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Chris Dumez
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2019-07-19 15:33 PDT by Chris Dumez
Modified: 2019-07-25 09:43 PDT (History)
7 users (show)

See Also:


Attachments
Patch (4.03 KB, patch)
2019-07-19 15:40 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff
Patch (4.12 KB, patch)
2019-07-19 15:42 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff
Patch (4.90 KB, patch)
2019-07-19 15:44 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff
Patch (6.96 KB, patch)
2019-07-19 15:53 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Chris Dumez 2019-07-19 15:33:35 PDT
Micro-optimize HashMap IPC encoder / decoder.
Comment 1 Chris Dumez 2019-07-19 15:40:03 PDT
Created attachment 374511 [details]
Patch
Comment 2 Chris Dumez 2019-07-19 15:42:32 PDT
Created attachment 374512 [details]
Patch
Comment 3 Chris Dumez 2019-07-19 15:44:24 PDT
Created attachment 374513 [details]
Patch
Comment 4 Chris Dumez 2019-07-19 15:53:33 PDT
Created attachment 374515 [details]
Patch
Comment 5 Radar WebKit Bug Importer 2019-07-20 12:28:20 PDT
<rdar://problem/53351435>
Comment 6 Geoffrey Garen 2019-07-20 17:34:13 PDT
Comment on attachment 374515 [details]
Patch

r=me
Comment 7 WebKit Commit Bot 2019-07-20 18:04:13 PDT
Comment on attachment 374515 [details]
Patch

Clearing flags on attachment: 374515

Committed r247672: <https://trac.webkit.org/changeset/247672>
Comment 8 WebKit Commit Bot 2019-07-20 18:04:14 PDT
All reviewed patches have been landed.  Closing bug.
Comment 9 Michael Catanzaro 2019-07-25 09:05:50 PDT
Comment on attachment 374515 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=374515&action=review

> Source/WebKit/ChangeLog:17
> +        HashMap::size() returns an 'unsigned int' type. Finally, update the modern
> +        decoder to WTFMove(hashMap) when returning. Because the function returns an
> +        Optional<HashMap> and not a HashMap, I do not believe we get return value
> +        optimization (RVO).

Apparently we actually do. This triggered a huge -Wredundant-move warning spam in GCC. The full warnings are huge but the interesting parts look like this:

DerivedSources/ForwardingHeaders/wtf/StdLibExtras.h:568:64: warning: redundant move in return statement [-Wredundant-move]
  568 | #define WTFMove(value) std::move<WTF::CheckMoveParameter>(value)
      |                                                                ^
../../Source/WebKit/Platform/IPC/ArgumentCoders.h:400:16: note: in expansion of macro ‘WTFMove’
  400 |         return WTFMove(hashMap);
      |                ^~~~~~~
DerivedSources/ForwardingHeaders/wtf/StdLibExtras.h:568:64: note: remove ‘std::move’ call
  568 | #define WTFMove(value) std::move<WTF::CheckMoveParameter>(value)
      |                                                                ^
../../Source/WebKit/Platform/IPC/ArgumentCoders.h:400:16: note: in expansion of macro ‘WTFMove’
  400 |         return WTFMove(hashMap);
      |                ^~~~~~~
Comment 10 Michael Catanzaro 2019-07-25 09:07:14 PDT
Committed r247823: <https://trac.webkit.org/changeset/247823>
Comment 11 Chris Dumez 2019-07-25 09:17:02 PDT
(In reply to Michael Catanzaro from comment #10)
> Committed r247823: <https://trac.webkit.org/changeset/247823>

Per spec:
"""
in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value
"""

The return type if not the same so I would not expect RVO to apply here. Did you actually check your compiler warning is not bogus before reverting?
Comment 12 Michael Catanzaro 2019-07-25 09:28:35 PDT
Maybe you're right about that, but WTF::Optional doesn't have a move constructor (it's explicitly deleted), so I think it's still going to copy despite the WTFMove(). If so, I'd say the warning message could certainly stand to be improved.
Comment 13 Chris Dumez 2019-07-25 09:32:25 PDT
(In reply to Michael Catanzaro from comment #12)
> Maybe you're right about that, but WTF::Optional doesn't have a move
> constructor (it's explicitly deleted), so I think it's still going to copy
> despite the WTFMove(). If so, I'd say the warning message could certainly
> stand to be improved.

Huh?

  Optional(Optional&& rhs) __NOEXCEPT_(detail_::is_nothrow_move_constructible<T>::value)
  : OptionalBase<T>()
  {
    if (rhs.initialized()) {
        ::new (static_cast<void*>(dataptr())) T(std::move(*rhs));
        OptionalBase<T>::init_ = true;
        rhs.clear();
    }
  }

  constexpr Optional(const T& v) : OptionalBase<T>(v) {}

  constexpr Optional(T&& v) : OptionalBase<T>(detail_::constexpr_move(v)) {}
Comment 14 Michael Catanzaro 2019-07-25 09:35:08 PDT
Yeah, the class is confusing. It has a constructor here:

  Optional(Optional&& rhs) __NOEXCEPT_(detail_::is_nothrow_move_constructible<T>::value)
  : OptionalBase<T>()
  {
    if (rhs.initialized()) {
        ::new (static_cast<void*>(dataptr())) T(std::move(*rhs));
        OptionalBase<T>::init_ = true;
        rhs.clear();
    }
  }

But I think that won't be used here because you don't have an Optional already.

But there's a constexpr one below:

  constexpr Optional(T&& v) : OptionalBase<T>(detail_::constexpr_move(v)) {}

Maybe that one gets used?

I was looking at:

  Optional(T&&) = delete;

But that's actually a specialization for class Optional<T&>, where T is a reference type... so move constructor is deleted only in that case. Very confusing.

Regardless, my experience with suspected compiler bugs is they're few and far between. Usually it's smarter than the humans. Certainly smarter than me. :)
Comment 15 Chris Dumez 2019-07-25 09:38:18 PDT
(In reply to Michael Catanzaro from comment #14)
> Yeah, the class is confusing. It has a constructor here:
> 
>   Optional(Optional&& rhs)
> __NOEXCEPT_(detail_::is_nothrow_move_constructible<T>::value)
>   : OptionalBase<T>()
>   {
>     if (rhs.initialized()) {
>         ::new (static_cast<void*>(dataptr())) T(std::move(*rhs));
>         OptionalBase<T>::init_ = true;
>         rhs.clear();
>     }
>   }
> 
> But I think that won't be used here because you don't have an Optional
> already.
> 
> But there's a constexpr one below:
> 
>   constexpr Optional(T&& v) : OptionalBase<T>(detail_::constexpr_move(v)) {}
> 
> Maybe that one gets used?
> 
> I was looking at:
> 
>   Optional(T&&) = delete;
> 
> But that's actually a specialization for class Optional<T&>, where T is a
> reference type... so move constructor is deleted only in that case. Very
> confusing.
> 
> Regardless, my experience with suspected compiler bugs is they're few and
> far between. Usually it's smarter than the humans. Certainly smarter than
> me. :)

Ok, I have just validated that the HashMap copy constructor does not get called when IPC decoding after your change. So it looks like it is fine.
I am surprised the compiler is able to do RVO here but apparently it can.

And yes, it was calling this move constructor:
constexpr Optional(T&& v) : OptionalBase<T>(detail_::constexpr_move(v)) {}
Comment 16 Michael Catanzaro 2019-07-25 09:41:12 PDT
Thanks for checking!
Comment 17 Michael Catanzaro 2019-07-25 09:43:50 PDT
BTW the difference between Clang and GCC here is that Clang only has -Wpessimizing-move, where 'return WTFMove(foo)' actually *prevents* RVO from happening. GCC will additionally warn when the move is harmless but not doing anything, -Wredundant-move.