New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 592767 link

Starred by 1 user

Issue metadata

Status: Fixed
Owner:
Closed: Mar 2016
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Linux , Mac
Pri: 2
Type: Bug



Sign in to add a comment

WTF::Vector: incorrectly use memcpy for types that have user-defined move constructor/assignment.

Project Member Reported by yzshen@chromium.org, Mar 7 2016

Issue description

OS: Linux and Mac.

I tried debug GN non-component build on my Linux machine. mac_chromium_rel_ng and linux_chromium_rel_ng trybots showed the same problem.


What steps will reproduce the problem?
(1) Some types are incorrectly considered trivially move assignable, such as mojo::MoveOnlyType defined in the following file:
https://code.google.com/p/chromium/codesearch#chromium/src/mojo/public/cpp/bindings/tests/container_test_util.h&l=33
(2) Assume that you have a WTF::Vector<mojo::MoveOnlyType> vec.
(3) Resize |vec| to its capacity (say, |capacity0|)
(4) And then, resize |vec| again to an even bigger size (say, |capacity0 + 2|) to force a re-allocation.
(5) It is expected that mojo::MoveOnlyType's move constructor/assignment operator is called to move the existing elements to the new storage.
(6) However, memcpy() is used which is wrong.

One interesting finding is that the current mojo::MoveOnlyType uses MOVE_ONLY_TYPE_FOR_CPP_03 macro, which contains the following lines:
=========================================
 private:
  MoveOnlyType(const MoveOnlyType& other) = delete;
  void operator=(const MoveOnlyType& other) = delete;
=========================================

If I made the following changes then WTF::Vector will do the right thing:
=========================================
 private:
  MoveOnlyType(const MoveOnlyType& other) {}
  void operator=(const MoveOnlyType& other) {}
=========================================


+CC bratell@opera.com who originally wrote IsTriviallyMoveAssignable in wtf/TypeTraits.h
 
Components: Blink
Labels: OS-Linux OS-Mac
Components: -Blink Blink>Architecture
Owner: yutak@chromium.org
yutak@: Would you take a look at this?

Comment 4 by yutak@chromium.org, Mar 8 2016

Status: Started (was: Untriaged)
Yeah, I could confirm that type is detected as trivially movable; looking.

Comment 5 by yutak@chromium.org, Mar 8 2016

Cc: tzik@chromium.org
So the core issue here is __has_trivial_assign(T) is true if T's copy assignment
operator is declared as deleted. This is kind of surprising.

Maybe we could adjust the TypeTraits.h a little bit...?

Comment 6 by tzik@chromium.org, Mar 8 2016

IIUC, __has_trivial_assign means the assignment operator is trivial, but it does not imply the type is assignable.

From the spec:
> ISO/IEC 14882:2011, 12.8.25
> A copy/move assignment operator for class X is trivial if it is not user-provided and if
> — class X has no virtual functions (10.3) and no virtual base classes (10.1), and
> — the assignment operator selected to copy/move each direct base class subobject is trivial, and
> — for each non-static data member of X that is of class type (or array thereof), the assignment operator
> selected to copy/move that member is trivial;
> otherwise the copy/move assignment operator is non-trivial.

Since a deleted function is not considered user-provided, the copy assignment operator of mojo::MoveOnlyType is trivial even though it's deleted.
Can we check if it's assignable as well in IsTriviallyMoveAssignable?

Comment 7 by yutak@chromium.org, Mar 8 2016

> Since a deleted function is not considered user-provided, the copy assignment operator of mojo::MoveOnlyType is trivial even though it's deleted.
> Can we check if it's assignable as well in IsTriviallyMoveAssignable?

Yeah, I've started to think that is the least intrusive option here. This means that
we have to write std::is_assignable equivalents ourselves, since libstdc++ 4.6
doesn't provide it, which is a bit unfortunate, but definitely doable.

I investigated another option to use std::is_pod instead of __has_trivial_assign,
but that seemed infeasible since there are a lot of complexities around that.
Project Member

Comment 8 by bugdroid1@chromium.org, Mar 8 2016

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/4a08542fb0f317809a3fca5ff092cfa60c1e52ac

commit 4a08542fb0f317809a3fca5ff092cfa60c1e52ac
Author: yutak <yutak@chromium.org>
Date: Tue Mar 08 10:19:06 2016

WTF: Move TypeTraits.cpp to test-only target.

This patch renames TypeTraits.cpp to TypeTraitsTest.cpp and makes it
part of wtf_unittest instead of wtf target. Additionally, its content is
surrounded with anonymous namespace to indicate that the classes defined
there are not exposed in WTF namespace.

The file only contains static_assert assertions, so it doesn't have to
be compiled into wtf.

This change is a preparation of the fix for  bug 592767 .

BUG= 592767 

Review URL: https://codereview.chromium.org/1772163003

Cr-Commit-Position: refs/heads/master@{#379800}

[rename] https://crrev.com/4a08542fb0f317809a3fca5ff092cfa60c1e52ac/third_party/WebKit/Source/wtf/TypeTraitsTest.cpp
[modify] https://crrev.com/4a08542fb0f317809a3fca5ff092cfa60c1e52ac/third_party/WebKit/Source/wtf/wtf.gypi

Comment 9 by brat...@opera.com, Mar 8 2016

__has_trivial_assign() is old, way older than =delete and move semantics. Maybe there is something better in C++11 type traits?
Project Member

Comment 10 by bugdroid1@chromium.org, Mar 10 2016

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/d7225e41c5557ef72e5ca439fcf8287be37e7c0f

commit d7225e41c5557ef72e5ca439fcf8287be37e7c0f
Author: yutak <yutak@chromium.org>
Date: Thu Mar 10 04:05:01 2016

WTF: Fix Vector<T> memcpy'ing incorrectly for some T.

The core issue here is the implementation of IsTriviallyCopyAssignable
and IsTriviallyMoveAssignable was incorrect. They both use a compiler
builtin __has_trivial_assign(T), but it returns true if T's copy
assignment operator is declared as deleted.

To workaround that, a new type trait IsAssignable<T, From> is
implemented in the same way as std::is_assignable (as it's not available
at this time), and the assignability is used to limit the scope of
IsTrivially{Copy,Move}Assignable.

IsMoveAssignable isn't really right even with my patch for the reason
stated in the comments in the patch. I think it's impossible to
workaround that, though.

A bunch of static_asserts are added to test some invariants related to
this change.

BUG= 592767 

Review URL: https://codereview.chromium.org/1771303002

Cr-Commit-Position: refs/heads/master@{#380329}

[modify] https://crrev.com/d7225e41c5557ef72e5ca439fcf8287be37e7c0f/third_party/WebKit/Source/wtf/TypeTraits.h
[modify] https://crrev.com/d7225e41c5557ef72e5ca439fcf8287be37e7c0f/third_party/WebKit/Source/wtf/TypeTraitsTest.cpp
[modify] https://crrev.com/d7225e41c5557ef72e5ca439fcf8287be37e7c0f/third_party/WebKit/Source/wtf/VectorTest.cpp

Project Member

Comment 11 by bugdroid1@chromium.org, Mar 11 2016

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/1d3fb1ed5618c3ac47842ed8f9100a7b4cfdbc2a

commit 1d3fb1ed5618c3ac47842ed8f9100a7b4cfdbc2a
Author: yutak <yutak@chromium.org>
Date: Fri Mar 11 05:17:52 2016

WTF TypeTraits: Fix IsTrivially{DefaultConstructible,Destructible}.

This is a follow-up of an earlier CL:
https://codereview.chromium.org/1771303002/

This patch fixes two type traits so they can properly consider deleted
constructors and destructors. The strategy is pretty similar to the one
of the previous CL.

BUG= 592767 

Review URL: https://codereview.chromium.org/1785653002

Cr-Commit-Position: refs/heads/master@{#380519}

[modify] https://crrev.com/1d3fb1ed5618c3ac47842ed8f9100a7b4cfdbc2a/third_party/WebKit/Source/wtf/TypeTraits.h
[modify] https://crrev.com/1d3fb1ed5618c3ac47842ed8f9100a7b4cfdbc2a/third_party/WebKit/Source/wtf/TypeTraitsTest.cpp

Comment 12 by yutak@chromium.org, Mar 11 2016

Status: Fixed (was: Started)
I think this is fixed now.

Comment 13 by tkent@chromium.org, Jun 23 2016

Components: -Blink>Architecture Blink>Internals
Renaming Blink>Architecture to Blink>Internals

Sign in to add a comment