Bug 1092010 - part 1 - add move semantics to Pickle and IPC::Message; r=dvander
☠☠ backed out by b5703e3ef5de ☠ ☠
authorNathan Froyd <froydnj@mozilla.com>
Fri, 31 Oct 2014 11:20:43 -0400
changeset 213475 f3d36cf13ac10855861b82acd6f82692af675a3f
parent 213474 4a4eb24614d134748309b84d3104fa0deeb91b9b
child 213476 a7d4914ea11a1d1d81a3862fc71e003b38a7f06c
push id51241
push usernfroyd@mozilla.com
push dateSat, 01 Nov 2014 02:25:13 +0000
treeherdermozilla-inbound@a7d4914ea11a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs1092010
milestone36.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1092010 - part 1 - add move semantics to Pickle and IPC::Message; r=dvander
ipc/chromium/src/base/pickle.cc
ipc/chromium/src/base/pickle.h
ipc/chromium/src/chrome/common/ipc_message.cc
ipc/chromium/src/chrome/common/ipc_message.h
--- a/ipc/chromium/src/base/pickle.cc
+++ b/ipc/chromium/src/base/pickle.cc
@@ -139,16 +139,26 @@ Pickle::Pickle(const Pickle& other)
   uint32_t payload_size = header_size_ + other.header_->payload_size;
   bool resized = Resize(payload_size);
   if (!resized) {
     NS_ABORT_OOM(payload_size);
   }
   memcpy(header_, other.header_, payload_size);
 }
 
+Pickle::Pickle(Pickle&& other)
+  : header_(other.header_),
+    header_size_(other.header_size_),
+    capacity_(other.capacity_),
+    variable_buffer_offset_(other.variable_buffer_offset_) {
+  other.header_ = NULL;
+  other.capacity_ = 0;
+  other.variable_buffer_offset_ = 0;
+}
+
 Pickle::~Pickle() {
   if (capacity_ != kCapacityReadOnly)
     free(header_);
 }
 
 Pickle& Pickle::operator=(const Pickle& other) {
   if (header_size_ != other.header_size_ && capacity_ != kCapacityReadOnly) {
     free(header_);
@@ -159,16 +169,24 @@ Pickle& Pickle::operator=(const Pickle& 
   if (!resized) {
     NS_ABORT_OOM(other.header_size_ + other.header_->payload_size);
   }
   memcpy(header_, other.header_, header_size_ + other.header_->payload_size);
   variable_buffer_offset_ = other.variable_buffer_offset_;
   return *this;
 }
 
+Pickle& Pickle::operator=(Pickle&& other) {
+  std::swap(header_, other.header_);
+  std::swap(header_size_, other.header_size_);
+  std::swap(capacity_, other.capacity_);
+  std::swap(variable_buffer_offset_, other.variable_buffer_offset_);
+  return *this;
+}
+
 bool Pickle::ReadBool(void** iter, bool* result) const {
   DCHECK(iter);
 
   int tmp;
   if (!ReadInt(iter, &tmp))
     return false;
   DCHECK(0 == tmp || 1 == tmp);
   *result = tmp ? true : false;
--- a/ipc/chromium/src/base/pickle.h
+++ b/ipc/chromium/src/base/pickle.h
@@ -44,19 +44,23 @@ class Pickle {
   // instead the data is merely referenced by this Pickle.  Only const methods
   // should be used on the Pickle when initialized this way.  The header
   // padding size is deduced from the data length.
   Pickle(const char* data, int data_len);
 
   // Initializes a Pickle as a deep copy of another Pickle.
   Pickle(const Pickle& other);
 
+  Pickle(Pickle&& other);
+
   // Performs a deep copy.
   Pickle& operator=(const Pickle& other);
 
+  Pickle& operator=(Pickle&& other);
+
   // Returns the size of the Pickle's data.
   int size() const { return static_cast<int>(header_size_ +
                                              header_->payload_size); }
 
   // Returns the data for this Pickle.
   const void* data() const { return header_; }
 
   // Methods for reading the payload of the Pickle.  To read from the start of
--- a/ipc/chromium/src/chrome/common/ipc_message.cc
+++ b/ipc/chromium/src/chrome/common/ipc_message.cc
@@ -75,16 +75,28 @@ Message::Message(const Message& other) :
 #endif
 #ifdef MOZ_TASK_TRACER
   header()->source_event_id = other.header()->source_event_id;
   header()->parent_task_id = other.header()->parent_task_id;
   header()->source_event_type = other.header()->source_event_type;
 #endif
 }
 
+Message::Message(Message&& other) : Pickle(mozilla::Move(other)) {
+  InitLoggingVariables(other.name_);
+#if defined(OS_POSIX)
+  file_descriptor_set_ = other.file_descriptor_set_.forget();
+#endif
+#ifdef MOZ_TASK_TRACER
+  header()->source_event_id = other.header()->source_event_id;
+  header()->parent_task_id = other.header()->parent_task_id;
+  header()->source_event_type = other.header()->source_event_type;
+#endif
+}
+
 void Message::InitLoggingVariables(const char* const name) {
   name_ = name;
 #ifdef IPC_MESSAGE_LOG_ENABLED
   received_time_ = 0;
   dont_log_ = false;
   log_data_ = NULL;
 #endif
 }
@@ -98,16 +110,30 @@ Message& Message::operator=(const Messag
 #ifdef MOZ_TASK_TRACER
   header()->source_event_id = other.header()->source_event_id;
   header()->parent_task_id = other.header()->parent_task_id;
   header()->source_event_type = other.header()->source_event_type;
 #endif
   return *this;
 }
 
+Message& Message::operator=(Message&& other) {
+  *static_cast<Pickle*>(this) = mozilla::Move(other);
+  InitLoggingVariables(other.name_);
+#if defined(OS_POSIX)
+  file_descriptor_set_.swap(other.file_descriptor_set_);
+#endif
+#ifdef MOZ_TASK_TRACER
+  std::swap(header()->source_event_id, other.header()->source_event_id);
+  std::swap(header()->parent_task_id, other.header()->parent_task_id);
+  std::swap(header()->source_event_type, other.header()->source_event_type);
+#endif
+  return *this;
+}
+
 #ifdef IPC_MESSAGE_LOG_ENABLED
 void Message::set_sent_time(int64_t time) {
   DCHECK((header()->flags & HAS_SENT_TIME_BIT) == 0);
   header()->flags |= HAS_SENT_TIME_BIT;
   WriteInt64(time);
 }
 
 int64_t Message::sent_time() const {
--- a/ipc/chromium/src/chrome/common/ipc_message.h
+++ b/ipc/chromium/src/chrome/common/ipc_message.h
@@ -74,17 +74,19 @@ class Message : public Pickle {
           const char* const name="???");
 
   // Initializes a message from a const block of data.  The data is not copied;
   // instead the data is merely referenced by this message.  Only const methods
   // should be used on the message when initialized this way.
   Message(const char* data, int data_len);
 
   Message(const Message& other);
+  Message(Message&& other);
   Message& operator=(const Message& other);
+  Message& operator=(Message&& other);
 
   PriorityValue priority() const {
     return static_cast<PriorityValue>(header()->flags & PRIORITY_MASK);
   }
 
   void set_priority(int prio) {
     DCHECK((prio & ~PRIORITY_MASK) == 0);
     header()->flags = (header()->flags & ~PRIORITY_MASK) | prio;