Skip to content

Commit

Permalink
Bug 1379680. Add an ipc ByteBuf type. r=billm
Browse files Browse the repository at this point in the history
This adds a ByteBuf type that can be sent by taking
ownership of its buffer instead of having to make a copy.
  • Loading branch information
jrmuizel committed Nov 29, 2017
1 parent 07d53bd commit fba1664
Show file tree
Hide file tree
Showing 11 changed files with 184 additions and 11 deletions.
2 changes: 1 addition & 1 deletion gfx/layers/ipc/PWebRenderBridge.ipdl
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ parent:
sync Create(IntSize aSize);
async DeleteCompositorAnimations(uint64_t[] aIds);
async SetDisplayList(IntSize aSize, WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId,
LayoutSize aContentSize, ByteBuffer aDL, BuiltDisplayListDescriptor aDLDesc,
LayoutSize aContentSize, ByteBuf aDL, BuiltDisplayListDescriptor aDLDesc,
WebRenderScrollData aScrollData,
OpUpdateResource[] aResourceUpdates, Shmem[] aSmallShmems, Shmem[] aLargeShmems,
IdNamespace aIdNamespace, TimeStamp txnStartTime, TimeStamp fwdTime);
Expand Down
4 changes: 3 additions & 1 deletion gfx/layers/wr/WebRenderBridgeChild.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,9 @@ WebRenderBridgeChild::EndTransaction(const wr::LayoutSize& aContentSize,
MOZ_ASSERT(!mDestroyed);
MOZ_ASSERT(mIsInTransaction);

ByteBuffer dlData(Move(aDL.dl));
ByteBuf dlData(aDL.dl.inner.data, aDL.dl.inner.length, aDL.dl.inner.capacity);
aDL.dl.inner.capacity = 0;
aDL.dl.inner.data = nullptr;

TimeStamp fwdTime;
#if defined(ENABLE_FRAME_LATENCY_LOG)
Expand Down
4 changes: 2 additions & 2 deletions gfx/layers/wr/WebRenderBridgeParent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ WebRenderBridgeParent::RecvSetDisplayList(const gfx::IntSize& aSize,
const uint64_t& aFwdTransactionId,
const uint64_t& aTransactionId,
const wr::LayoutSize& aContentSize,
const wr::ByteBuffer& dl,
ipc::ByteBuf&& dl,
const wr::BuiltDisplayListDescriptor& dlDesc,
const WebRenderScrollData& aScrollData,
nsTArray<OpUpdateResource>&& aResourceUpdates,
Expand Down Expand Up @@ -609,7 +609,7 @@ WebRenderBridgeParent::RecvSetDisplayList(const gfx::IntSize& aSize,
gfx::Color clearColor(0.f, 0.f, 0.f, 0.f);
mApi->SetDisplayList(clearColor, wr::NewEpoch(wrEpoch), LayerSize(aSize.width, aSize.height),
mPipelineId, aContentSize,
dlDesc, dl.mData, dl.mLength,
dlDesc, dl.mData, dl.mLen,
resources);

ScheduleComposition();
Expand Down
2 changes: 1 addition & 1 deletion gfx/layers/wr/WebRenderBridgeParent.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent
const uint64_t& aFwdTransactionId,
const uint64_t& aTransactionId,
const wr::LayoutSize& aContentSize,
const wr::ByteBuffer& dl,
ipc::ByteBuf&& dl,
const wr::BuiltDisplayListDescriptor& dlDesc,
const WebRenderScrollData& aScrollData,
nsTArray<OpUpdateResource>&& aResourceUpdates,
Expand Down
5 changes: 5 additions & 0 deletions ipc/chromium/src/chrome/common/ipc_message_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ static inline void WriteParam(Message* m, const P& p) {
ParamTraits<P>::Write(m, p);
}

template <class P>
static inline void WriteParam(Message* m, P& p) {
ParamTraits<P>::Write(m, p);
}

template <class P>
static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m, PickleIterator* iter,
P* p) {
Expand Down
116 changes: 116 additions & 0 deletions ipc/glue/ByteBuf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/* A type that can be sent without needing to make a copy during
* serialization. In addition the receiver can take ownership of the
* data to avoid having to make an additional copy. */

#ifndef mozilla_ipc_ByteBuf_h
#define mozilla_ipc_ByteBuf_h

#include "ipc/IPCMessageUtils.h"

namespace mozilla {

namespace ipc {

class ByteBuf final
{
friend struct IPC::ParamTraits<mozilla::ipc::ByteBuf>;
public:
bool
Allocate(size_t aLength)
{
MOZ_ASSERT(mData == nullptr);
mData = (uint8_t*)malloc(aLength);
if (!mData) {
return false;
}
mLen = aLength;
mCapacity = aLength;
return true;
}

ByteBuf()
: mData(nullptr)
, mLen(0)
, mCapacity(0)
{}

ByteBuf(uint8_t *aData, size_t aLen, size_t aCapacity)
: mData(aData)
, mLen(aLen)
, mCapacity(aCapacity)
{}

ByteBuf(const ByteBuf& aFrom) = delete;

ByteBuf(ByteBuf&& aFrom)
: mData(aFrom.mData)
, mLen(aFrom.mLen)
, mCapacity(aFrom.mCapacity)
{
aFrom.mData = nullptr;
aFrom.mLen = 0;
aFrom.mCapacity = 0;
}

~ByteBuf()
{
free(mData);
}

uint8_t* mData;
size_t mLen;
size_t mCapacity;
};


} // namespace ipc
} // namespace mozilla


namespace IPC {

template<>
struct ParamTraits<mozilla::ipc::ByteBuf>
{
typedef mozilla::ipc::ByteBuf paramType;

// this is where we transfer the memory from the ByteBuf to IPDL, avoiding a copy
static void Write(Message* aMsg, paramType& aParam)
{
WriteParam(aMsg, aParam.mLen);
// hand over ownership of the buffer to the Message
aMsg->WriteBytesZeroCopy(aParam.mData, aParam.mLen, aParam.mCapacity);
aParam.mData = nullptr;
aParam.mCapacity = 0;
aParam.mLen = 0;
}

static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
// We make a copy from the BufferList so that we get a contigous result.
// For users the can handle a non-contiguous result using ExtractBuffers
// is an option, alternatively if the users don't need to take ownership of
// the data they can use the removed FlattenBytes (bug 1297981)
size_t length;
return ReadParam(aMsg, aIter, &length)
&& aResult->Allocate(length)
&& aMsg->ReadBytesInto(aIter, aResult->mData, length);
}

static void Log(const paramType& aParam, std::wstring* aLog)
{
aLog->append(L"(byte buf)");
}
};


} // namespace IPC


#endif // ifndef mozilla_ipc_Shmem_h
1 change: 1 addition & 0 deletions ipc/glue/ProtocolUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "IPCMessageStart.h"
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/Attributes.h"
#include "mozilla/ipc/ByteBuf.h"
#include "mozilla/ipc/FileDescriptor.h"
#include "mozilla/ipc/Shmem.h"
#include "mozilla/ipc/Transport.h"
Expand Down
1 change: 1 addition & 0 deletions ipc/glue/moz.build
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ EXPORTS.mozilla.ipc += [
'BackgroundParent.h',
'BackgroundUtils.h',
'BrowserProcessSubThread.h',
'ByteBuf.h',
'CrashReporterClient.h',
'CrashReporterHost.h',
'CrashReporterMetadataShmem.h',
Expand Down
1 change: 1 addition & 0 deletions ipc/ipdl/ipdl/builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
'nsDependentSubstring',
'nsDependentCSubstring',
'mozilla::ipc::Shmem',
'mozilla::ipc::ByteBuf',
'mozilla::ipc::FileDescriptor'
)

Expand Down
43 changes: 37 additions & 6 deletions ipc/ipdl/ipdl/lower.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,9 @@ def visitArrayType(self, a):
def visitShmemType(self, s):
return Type(self.typename(s))

def visitByteBufType(self, s):
return Type(self.typename(s))

def visitFDType(self, s):
return Type(self.typename(s))

Expand All @@ -586,13 +589,17 @@ def _cxxConstRefType(ipdltype, side):
if ipdltype.isIPDL() and ipdltype.isShmem():
t.ref = 1
return t
if ipdltype.isIPDL() and ipdltype.isByteBuf():
t.ref = 1
return t
t.const = 1
t.ref = 1
return t

def _cxxTypeNeedsMove(ipdltype):
return ipdltype.isIPDL() and (ipdltype.isArray() or
ipdltype.isShmem() or
ipdltype.isByteBuf() or
ipdltype.isEndpoint())

def _cxxMoveRefType(ipdltype, side):
Expand Down Expand Up @@ -768,6 +775,8 @@ def constRefExpr(self, thisexpr=None):
refexpr = self.refExpr(thisexpr)
if 'Shmem' == self.ipdltype.name():
refexpr = ExprCast(refexpr, Type('Shmem', ref=1), const=1)
if 'ByteBuf' == self.ipdltype.name():
refexpr = ExprCast(refexpr, Type('ByteBuf', ref=1), const=1)
if 'FileDescriptor' == self.ipdltype.name():
refexpr = ExprCast(refexpr, Type('FileDescriptor', ref=1), const=1)
return refexpr
Expand Down Expand Up @@ -931,6 +940,8 @@ def defaultValue(self):
def getConstValue(self):
v = ExprDeref(self.callGetConstPtr())
# sigh
if 'ByteBuf' == self.ipdltype.name():
v = ExprCast(v, Type('ByteBuf', ref=1), const=1)
if 'Shmem' == self.ipdltype.name():
v = ExprCast(v, Type('Shmem', ref=1), const=1)
if 'FileDescriptor' == self.ipdltype.name():
Expand Down Expand Up @@ -1870,6 +1881,11 @@ def visitShmemType(self, s):
self.visited.add(s)
self.maybeTypedef('mozilla::ipc::Shmem', 'Shmem')

def visitByteBufType(self, s):
if s in self.visited: return
self.visited.add(s)
self.maybeTypedef('mozilla::ipc::ByteBuf', 'ByteBuf')

def visitFDType(self, s):
if s in self.visited: return
self.visited.add(s)
Expand Down Expand Up @@ -3384,6 +3400,7 @@ def implementPickling(self):
class findSpecialTypes(TypeVisitor):
def visitActorType(self, a): specialtypes.add(a)
def visitShmemType(self, s): specialtypes.add(s)
def visitByteBufType(self, s): specialtypes.add(s)
def visitFDType(self, s): specialtypes.add(s)
def visitStructType(self, s):
specialtypes.add(s)
Expand All @@ -3408,12 +3425,13 @@ def visitArrayType(self, a):
ret.ipdltype.accept(findSpecialTypes())

for t in specialtypes:
if t.isActor(): self.implementActorPickling(t)
elif t.isArray(): self.implementSpecialArrayPickling(t)
elif t.isShmem(): self.implementShmemPickling(t)
elif t.isFD(): self.implementFDPickling(t)
elif t.isStruct(): self.implementStructPickling(t)
elif t.isUnion(): self.implementUnionPickling(t)
if t.isActor(): self.implementActorPickling(t)
elif t.isArray(): self.implementSpecialArrayPickling(t)
elif t.isShmem(): self.implementShmemPickling(t)
elif t.isByteBuf(): self.implementByteBufPickling(t)
elif t.isFD(): self.implementFDPickling(t)
elif t.isStruct(): self.implementStructPickling(t)
elif t.isUnion(): self.implementUnionPickling(t)
else:
assert 0 and 'unknown special type'

Expand All @@ -3434,6 +3452,19 @@ def implementGenericPickling(self):

self.cls.addstmts([ write, Whitespace.NL, read, Whitespace.NL ])

def implementByteBufPickling(self, bytebuftype):
var = self.var
msgvar = self.msgvar
itervar = self.itervar
intype = _cxxRefType(bytebuftype, self.side)

write = MethodDefn(self.writeMethodDecl(intype, var))
write.addstmt(StmtExpr(ExprCall(ExprVar('IPC::WriteParam'),
args=[ msgvar, var ])))

self.cls.addstmts([ write, Whitespace.NL ])
# the rest of generic pickling will work fine for us

def implementActorPickling(self, actortype):
# Note that we pickle based on *protocol* type and *not* actor
# type. The actor type includes a |nullable| qualifier, but
Expand Down
16 changes: 16 additions & 0 deletions ipc/ipdl/ipdl/type.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ def visitArrayType(self, a, *args):
def visitShmemType(self, s, *args):
pass

def visitByteBufType(self, s, *args):
pass

def visitShmemChmodType(self, c, *args):
c.shmem.accept(self)

Expand Down Expand Up @@ -147,6 +150,7 @@ def isArray(self): return False
def isAtom(self): return True
def isCompound(self): return False
def isShmem(self): return False
def isByteBuf(self): return False
def isFD(self): return False
def isEndpoint(self): return False

Expand Down Expand Up @@ -368,6 +372,16 @@ def name(self):
def fullname(self):
return str(self.qname)

class ByteBufType(IPDLType):
def __init__(self, qname):
self.qname = qname
def isByteBuf(self): return True

def name(self):
return self.qname.baseid
def fullname(self):
return str(self.qname)

class FDType(IPDLType):
def __init__(self, qname):
self.qname = qname
Expand Down Expand Up @@ -725,6 +739,8 @@ def visitUsingStmt(self, using):
fullname = None
if fullname == 'mozilla::ipc::Shmem':
ipdltype = ShmemType(using.type.spec)
elif fullname == 'mozilla::ipc::ByteBuf':
ipdltype = ByteBufType(using.type.spec)
elif fullname == 'mozilla::ipc::FileDescriptor':
ipdltype = FDType(using.type.spec)
else:
Expand Down

0 comments on commit fba1664

Please sign in to comment.