Bug 1465287 Part 9 - Allow copying IPDL messages, r=froydnj.
authorBrian Hackett <bhackett1024@gmail.com>
Sun, 22 Jul 2018 11:53:23 +0000
changeset 427734 c9baf27742536134040a635d6f0b9528874d6bff
parent 427733 271b647d862700217f3fdbd9cce4f2b0e1e48274
child 427735 601b20ba619baff88c910f3a5edb1482be798585
push id34314
push usercsabou@mozilla.com
push dateMon, 23 Jul 2018 09:31:12 +0000
treeherdermozilla-central@143984185dce [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1465287
milestone63.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 1465287 Part 9 - Allow copying IPDL messages, r=froydnj.
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
mfbt/BufferList.h
--- a/ipc/chromium/src/base/pickle.cc
+++ b/ipc/chromium/src/base/pickle.cc
@@ -170,16 +170,24 @@ Pickle& Pickle::operator=(Pickle&& other
   buffers_ = std::move(tmp);
 
   //std::swap(buffers_, other.buffers_);
   std::swap(header_, other.header_);
   std::swap(header_size_, other.header_size_);
   return *this;
 }
 
+void Pickle::CopyFrom(const Pickle& other) {
+  MOZ_ALWAYS_TRUE(buffers_.CopyFrom(other.buffers_));
+  MOZ_ASSERT(other.header_ == reinterpret_cast<const Header*>(other.buffers_.Start()));
+
+  header_ = reinterpret_cast<Header*>(buffers_.Start());
+  header_size_ = other.header_size_;
+}
+
 bool Pickle::ReadBool(PickleIterator* 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
@@ -73,16 +73,18 @@ class Pickle {
 
   Pickle(Pickle&& other);
 
   // Performs a deep copy.
   Pickle& operator=(const Pickle& other) = delete;
 
   Pickle& operator=(Pickle&& other);
 
+  void CopyFrom(const Pickle& other);
+
   // Returns the size of the Pickle's data.
   uint32_t size() const { return header_size_ + header_->payload_size; }
 
   typedef mozilla::BufferList<InfallibleAllocPolicy> BufferList;
 
   const BufferList& Buffers() const { return buffers_; }
 
   uint32_t CurrentSize() const { return buffers_.Size(); }
--- a/ipc/chromium/src/chrome/common/ipc_message.cc
+++ b/ipc/chromium/src/chrome/common/ipc_message.cc
@@ -140,16 +140,22 @@ Message::ForInterruptDispatchError()
 Message& Message::operator=(Message&& other) {
   *static_cast<Pickle*>(this) = std::move(other);
 #if defined(OS_POSIX)
   file_descriptor_set_.swap(other.file_descriptor_set_);
 #endif
   return *this;
 }
 
+void Message::CopyFrom(const Message& other) {
+  Pickle::CopyFrom(other);
+#if defined(OS_POSIX)
+  file_descriptor_set_ = other.file_descriptor_set_;
+#endif
+}
 
 #if defined(OS_POSIX)
 bool Message::WriteFileDescriptor(const base::FileDescriptor& descriptor) {
   // We write the index of the descriptor so that we don't have to
   // keep the current descriptor as extra decoding state when deserialising.
   // Also, we rely on each file descriptor being accompanied by sizeof(int)
   // bytes of data in the message. See the comment for input_cmsg_buf_.
   WriteInt(file_descriptor_set()->size());
--- a/ipc/chromium/src/chrome/common/ipc_message.h
+++ b/ipc/chromium/src/chrome/common/ipc_message.h
@@ -208,16 +208,18 @@ class Message : public Pickle {
 
   Message(const char* data, int data_len);
 
   Message(const Message& other) = delete;
   Message(Message&& other);
   Message& operator=(const Message& other) = delete;
   Message& operator=(Message&& other);
 
+  void CopyFrom(const Message& other);
+
   // Helper method for the common case (default segmentCapacity, recording
   // the write latency of messages) of IPDL message creation.  This helps
   // move the malloc and some of the parameter setting out of autogenerated
   // code.
   static Message* IPDLMessage(int32_t routing_id,
                               msgid_t type,
                               HeaderFlags flags);
 
--- a/mfbt/BufferList.h
+++ b/mfbt/BufferList.h
@@ -130,16 +130,38 @@ class BufferList : private AllocPolicy
   {
     MOZ_ASSERT(mSegments.empty());
     MOZ_ASSERT(aInitialCapacity != 0);
     MOZ_ASSERT(aInitialCapacity % kSegmentAlignment == 0);
 
     return AllocateSegment(aInitialSize, aInitialCapacity);
   }
 
+  bool CopyFrom(const BufferList& aOther)
+  {
+    MOZ_ASSERT(mOwning);
+
+    Clear();
+
+    // We don't make an exact copy of aOther. Instead, create a single segment
+    // with enough space to hold all data in aOther.
+    if (!Init(aOther.mSize, (aOther.mSize + kSegmentAlignment - 1) & ~(kSegmentAlignment - 1))) {
+      return false;
+    }
+
+    size_t offset = 0;
+    for (const Segment& segment : aOther.mSegments) {
+      memcpy(Start() + offset, segment.mData, segment.mSize);
+      offset += segment.mSize;
+    }
+    MOZ_ASSERT(offset == mSize);
+
+    return true;
+  }
+
   // Returns the sum of the sizes of all the buffers.
   size_t Size() const { return mSize; }
 
   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
   {
     size_t size = mSegments.sizeOfExcludingThis(aMallocSizeOf);
     for (Segment& segment : mSegments) {
       size += aMallocSizeOf(segment.Start());