RESOLVED FIXED 115033
Add move semantics to RefPtr
https://bugs.webkit.org/show_bug.cgi?id=115033
Summary Add move semantics to RefPtr
Mikhail Pozdnyakov
Reported 2013-04-23 06:32:20 PDT
SSIA. That would allow us to obviate unnecessary reffing/ureffing when RefPtr is created or assigned from rvalue references.
Attachments
patch (2.92 KB, patch)
2013-04-23 07:33 PDT, Mikhail Pozdnyakov
andersca: review-
patch v2 (2.20 KB, patch)
2013-04-23 07:52 PDT, Mikhail Pozdnyakov
andersca: review-
patch v3 (2.90 KB, patch)
2013-04-23 08:28 PDT, Mikhail Pozdnyakov
benjamin: review-
patch v4 (2.84 KB, patch)
2013-04-24 04:38 PDT, Mikhail Pozdnyakov
benjamin: review-
patch v5 (2.93 KB, patch)
2013-04-25 12:11 PDT, Mikhail Pozdnyakov
benjamin: review+
buildbot: commit-queue-
patch v6 (2.93 KB, patch)
2013-04-26 02:09 PDT, Mikhail Pozdnyakov
andersca: review+
Mikhail Pozdnyakov
Comment 1 2013-04-23 07:33:46 PDT
WebKit Commit Bot
Comment 2 2013-04-23 07:35:49 PDT
Attachment 199233 [details] did not pass style-queue: Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'Source/WTF/ChangeLog', u'Source/WTF/wtf/RefPtr.h']" exit_code: 1 Source/WTF/wtf/RefPtr.h:84: Missing spaces around && [whitespace/operators] [3] Total errors found: 1 in 2 files If any of these errors are false positives, please file a bug against check-webkit-style.
Anders Carlsson
Comment 3 2013-04-23 07:44:02 PDT
Comment on attachment 199233 [details] patch View in context: https://bugs.webkit.org/attachment.cgi?id=199233&action=review This is great, but I'd appreciate if you could upload a new patch so we can let the EWS bots chew at it - it's a pretty fundamental change and it could break the build in weird wais. > Source/WTF/wtf/RefPtr.h:47 > + ALWAYS_INLINE RefPtr(RefPtr&& o) : m_ptr(o.get()) { o.m_ptr = 0; } I think this would read better as RefPtr(RefPtr&& o) : m_ptr(o.release().leakRef()) { } > Source/WTF/wtf/RefPtr.h:48 > + template<typename U> RefPtr(RefPtr<U>&& o) : m_ptr(o.get()) { o.m_ptr = 0; } Same thing here. > Source/WTF/wtf/RefPtr.h:163 > + if (m_ptr != o.get()) { > + derefIfNotNull(m_ptr); > + m_ptr = o.get(); > + o.m_ptr = 0; > + } > + return *this; I think this could just be m_ptr = o.release(); > Source/WTF/wtf/RefPtr.h:172 > + if (m_ptr != o.get()) { > + derefIfNotNull(m_ptr); > + m_ptr = o.get(); > + o.m_ptr = 0; > + } Ditto.
Mikhail Pozdnyakov
Comment 4 2013-04-23 07:52:44 PDT
Created attachment 199236 [details] patch v2 Updated due to comments from Anders. Thanks Anders!
Anders Carlsson
Comment 5 2013-04-23 08:02:31 PDT
Comment on attachment 199236 [details] patch v2 View in context: https://bugs.webkit.org/attachment.cgi?id=199236&action=review > Source/WTF/wtf/RefPtr.h:85 > + RefPtr& operator=(RefPtr&& o) { m_ptr = o.release(); } > + template<typename U> RefPtr& operator=(RefPtr<U>&& o) { m_ptr = o.release(); } These will cause a memory leak now, and return *this is gone. Let's change them back into what you had before; something like: if (m_ptr != o.m_ptr)) { derefIfNotNull(m_ptr); m_ptr = o.release().leakRef(); } return *this;
Mikhail Pozdnyakov
Comment 6 2013-04-23 08:19:04 PDT
(In reply to comment #5) > (From update of attachment 199236 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=199236&action=review > > > Source/WTF/wtf/RefPtr.h:85 > > + RefPtr& operator=(RefPtr&& o) { m_ptr = o.release(); } > > + template<typename U> RefPtr& operator=(RefPtr<U>&& o) { m_ptr = o.release(); } > > These will cause a memory leak now, and return *this is gone. omg! that's my absent-mindedness :(
Mikhail Pozdnyakov
Comment 7 2013-04-23 08:28:40 PDT
Created attachment 199244 [details] patch v3 fixed assignment operators :/
WebKit Commit Bot
Comment 8 2013-04-23 08:29:38 PDT
Attachment 199244 [details] did not pass style-queue: Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'Source/WTF/ChangeLog', u'Source/WTF/wtf/RefPtr.h']" exit_code: 1 Source/WTF/wtf/RefPtr.h:86: Missing spaces around && [whitespace/operators] [3] Total errors found: 1 in 2 files If any of these errors are false positives, please file a bug against check-webkit-style.
Alexey Proskuryakov
Comment 9 2013-04-23 10:30:56 PDT
> That would allow us to obviate unnecessary reffing/ureffing when RefPtr is created or assigned from rvalue references. Do we have examples of that in WebKit now? We are supposed to use PassRefPtr for poor man's move semantics. To be clear, I certainly don't object to this change.
Benjamin Poulain
Comment 10 2013-04-23 11:10:22 PDT
(In reply to comment #9) > > That would allow us to obviate unnecessary reffing/ureffing when RefPtr is created or assigned from rvalue references. > > Do we have examples of that in WebKit now? We are supposed to use PassRefPtr for poor man's move semantics. There is no explicit use of rvalue reference, but clang is smart enough to use it in some cases.
Benjamin Poulain
Comment 11 2013-04-23 11:19:09 PDT
Comment on attachment 199244 [details] patch v3 View in context: https://bugs.webkit.org/attachment.cgi?id=199244&action=review > Source/WTF/wtf/RefPtr.h:160 > + if (m_ptr != o.get()) { > + derefIfNotNull(m_ptr); > + m_ptr = o.release().leakRef(); > + } > + return *this; I don't understand why you do this. If you have RefPtr a = [foobar]; RefPtr b = a; a = std::move(b); "b" is unchanged, and the refcount is +2. This is counter-intuitive for move semantic. > Source/WTF/wtf/RefPtr.h:169 > + if (m_ptr != o.get()) { > + derefIfNotNull(m_ptr); > + m_ptr = o.release().leakRef(); > + } > + return *this; ditto
Mikhail Pozdnyakov
Comment 12 2013-04-24 04:38:19 PDT
Created attachment 199413 [details] patch v4 Addresses Benjamin's concern.
WebKit Commit Bot
Comment 13 2013-04-24 04:40:28 PDT
Attachment 199413 [details] did not pass style-queue: Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'Source/WTF/ChangeLog', u'Source/WTF/wtf/RefPtr.h']" exit_code: 1 Source/WTF/wtf/RefPtr.h:86: Missing spaces around && [whitespace/operators] [3] Total errors found: 1 in 2 files If any of these errors are false positives, please file a bug against check-webkit-style.
Benjamin Poulain
Comment 14 2013-04-24 14:42:05 PDT
Comment on attachment 199413 [details] patch v4 View in context: https://bugs.webkit.org/attachment.cgi?id=199413&action=review > Source/WTF/wtf/RefPtr.h:159 > + T* ptr = m_ptr; > + m_ptr = o.release().leakRef(); > + derefIfNotNull(ptr); > + return *this; With this, what if I do this? RefPtr a = [...]; a = std::move(a);
Mikhail Pozdnyakov
Comment 15 2013-04-25 01:26:23 PDT
(In reply to comment #14) > (From update of attachment 199413 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=199413&action=review > > > Source/WTF/wtf/RefPtr.h:159 > > + T* ptr = m_ptr; > > + m_ptr = o.release().leakRef(); > > + derefIfNotNull(ptr); > > + return *this; > > With this, what if I do this? > > RefPtr a = [...]; > a = std::move(a); mm, wouldn't it mean that we do not care about 'a' anymore? so that looks like caller's fault. btw, in RetainPtr we have exactly same implementation: template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(RetainPtr<T>&& o) { adoptCF(o.leakRef()); return *this; } and template<typename T> inline void RetainPtr<T>::adoptCF(PtrType optr) { PtrType ptr = m_ptr; m_ptr = optr; if (ptr) CFRelease(ptr); }
Anders Carlsson
Comment 16 2013-04-25 08:18:08 PDT
(In reply to comment #11) > (From update of attachment 199244 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=199244&action=review > > > Source/WTF/wtf/RefPtr.h:160 > > + if (m_ptr != o.get()) { > > + derefIfNotNull(m_ptr); > > + m_ptr = o.release().leakRef(); > > + } > > + return *this; > > I don't understand why you do this. My mistake, I think this check should just be: if (this != &o) { ... }
Mikhail Pozdnyakov
Comment 17 2013-04-25 08:42:15 PDT
(In reply to comment #15) > (In reply to comment #14) > > (From update of attachment 199413 [details] [details]) > > View in context: https://bugs.webkit.org/attachment.cgi?id=199413&action=review > > > > > Source/WTF/wtf/RefPtr.h:159 > > > + T* ptr = m_ptr; > > > + m_ptr = o.release().leakRef(); > > > + derefIfNotNull(ptr); > > > + return *this; > > > > With this, what if I do this? > > > > RefPtr a = [...]; > > a = std::move(a); > > mm, wouldn't it mean that we do not care about 'a' anymore? so that looks like caller's fault. > btw, in RetainPtr we have exactly same implementation: > template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(RetainPtr<T>&& o) > { > adoptCF(o.leakRef()); > return *this; > } > > and > > template<typename T> inline void RetainPtr<T>::adoptCF(PtrType optr) > { > PtrType ptr = m_ptr; > m_ptr = optr; > if (ptr) > CFRelease(ptr); > } yeah, with RetainPtr it's different as it\s releasing m_ptr which is 0 after leakPtr() call.
Mikhail Pozdnyakov
Comment 18 2013-04-25 12:11:26 PDT
Created attachment 199733 [details] patch v5 Fixed '=' operator.
WebKit Commit Bot
Comment 19 2013-04-25 12:12:26 PDT
Attachment 199733 [details] did not pass style-queue: Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'Source/WTF/ChangeLog', u'Source/WTF/wtf/RefPtr.h']" exit_code: 1 Source/WTF/wtf/RefPtr.h:86: Missing spaces around && [whitespace/operators] [3] Total errors found: 1 in 2 files If any of these errors are false positives, please file a bug against check-webkit-style.
Build Bot
Comment 20 2013-04-25 13:16:04 PDT
Comment on attachment 199733 [details] patch v5 Attachment 199733 [details] did not pass mac-wk2-ews (mac-wk2): Output: http://webkit-queues.appspot.com/results/144200
Build Bot
Comment 21 2013-04-25 13:24:26 PDT
Darin Adler
Comment 22 2013-04-25 14:22:03 PDT
Comment on attachment 199733 [details] patch v5 View in context: https://bugs.webkit.org/attachment.cgi?id=199733&action=review > Source/WTF/wtf/RefPtr.h:168 > + if (this != &o) { > + derefIfNotNull(m_ptr); > + m_ptr = o.release().leakRef(); > + } It’s difficult to get this right; often this and &o are not objects of the same type, so we can’t compare them. I suggest we instead consider the canonical operator= implementation: RefPtr<T> ptr = o; swap(ptr); return *this; We could use this for both operator= overloads. As long as it compiles to efficient-enough code.
Build Bot
Comment 23 2013-04-25 14:23:56 PDT
Anders Carlsson
Comment 24 2013-04-25 14:27:34 PDT
(In reply to comment #22) . > > I suggest we instead consider the canonical operator= implementation: > > RefPtr<T> ptr = o; > swap(ptr); > return *this; I like that. The first row should be RefPtr<T> ptr = std::move(o);
Mikhail Pozdnyakov
Comment 25 2013-04-26 01:54:10 PDT
(In reply to comment #24) > (In reply to comment #22) > . > > > > I suggest we instead consider the canonical operator= implementation: > > > > RefPtr<T> ptr = o; > > swap(ptr); > > return *this; > > I like that. The first row should be > > RefPtr<T> ptr = std::move(o); That's great! but how about just RefPtr<T>(std::move(o)).swap(*this); return *this;
Mikhail Pozdnyakov
Comment 26 2013-04-26 02:09:44 PDT
Created attachment 199804 [details] patch v6 Canonical '=' operator implementation.
WebKit Commit Bot
Comment 27 2013-04-26 02:12:14 PDT
Attachment 199804 [details] did not pass style-queue: Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'Source/WTF/ChangeLog', u'Source/WTF/wtf/RefPtr.h']" exit_code: 1 Source/WTF/wtf/RefPtr.h:87: Missing spaces around && [whitespace/operators] [3] Total errors found: 1 in 2 files If any of these errors are false positives, please file a bug against check-webkit-style.
Anders Carlsson
Comment 28 2013-04-26 07:36:27 PDT
Comment on attachment 199804 [details] patch v6 (In reply to comment #25) > That's great! but how about just > > RefPtr<T>(std::move(o)).swap(*this); > return *this; I think it's easier to read with an explicit temporary. Please make that change, r=me.
Mikhail Pozdnyakov
Comment 29 2013-04-26 07:55:37 PDT
Note You need to log in before you can comment on or make changes to this bug.