mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-27 04:38:02 +00:00
Bug 1523996 - part 5 - bulk-read/write adjacent POD fields in IPDL-defined structs; r=Alex_Gaynor
Now that fields are packed nicely, we can take advantage of the contiguous layout of POD fields and read/write all the POD fields of a given size in a single read/write call. For many structs, this should have little or no effect, but for large structs such as LoadInfoArgs, this reduces the number of function calls by ~50%. Differential Revision: https://phabricator.services.mozilla.com/D22001 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
c5829037f6
commit
14c0cbba56
@ -1901,6 +1901,47 @@ class _ParamTraits():
|
||||
block.addstmts(cls.writeSentinel(msgvar, sentinelKey))
|
||||
return block
|
||||
|
||||
@classmethod
|
||||
def bulkSentinelKey(cls, fields):
|
||||
return ' | '.join(f.basename for f in fields)
|
||||
|
||||
@classmethod
|
||||
def checkedBulkWrite(cls, size, fields):
|
||||
block = Block()
|
||||
first = fields[0]
|
||||
|
||||
block.addstmts([
|
||||
StmtExpr(ExprCall(ExprSelect(cls.msgvar, '->', 'WriteBytes'),
|
||||
args=[ExprAddrOf(ExprCall(first.getMethod(thisexpr=cls.var,
|
||||
sel='.'))),
|
||||
ExprLiteral.Int(size * len(fields))]))
|
||||
])
|
||||
block.addstmts(cls.writeSentinel(cls.msgvar, cls.bulkSentinelKey(fields)))
|
||||
|
||||
return block
|
||||
|
||||
@classmethod
|
||||
def checkedBulkRead(cls, size, fields):
|
||||
block = Block()
|
||||
first = fields[0]
|
||||
|
||||
readbytes = ExprCall(ExprSelect(cls.msgvar, '->', 'ReadBytesInto'),
|
||||
args=[cls.itervar,
|
||||
ExprAddrOf(ExprCall(first.getMethod(thisexpr=cls.var,
|
||||
sel='->'))),
|
||||
ExprLiteral.Int(size * len(fields))])
|
||||
ifbad = StmtIf(ExprNot(readbytes))
|
||||
errmsg = 'Error bulk reading fields from %s' % first.ipdltype.name()
|
||||
ifbad.addifstmts([cls.fatalError(errmsg),
|
||||
StmtReturn.FALSE])
|
||||
block.addstmt(ifbad)
|
||||
block.addstmts(cls.readSentinel(cls.msgvar,
|
||||
cls.itervar,
|
||||
cls.bulkSentinelKey(fields),
|
||||
errfnSentinel()(errmsg)))
|
||||
|
||||
return block
|
||||
|
||||
@classmethod
|
||||
def checkedRead(cls, ipdltype, var,
|
||||
msgvar, itervar, errfn,
|
||||
@ -2078,27 +2119,39 @@ class _ParamTraits():
|
||||
write = []
|
||||
read = []
|
||||
|
||||
# The iteration order here doesn't particularly matter, but we choose
|
||||
# member order for ideally better cache performance.
|
||||
for f in sd.fields_member_order():
|
||||
writefield = cls.checkedWrite(f.ipdltype,
|
||||
get('.', f),
|
||||
cls.msgvar,
|
||||
sentinelKey=f.basename,
|
||||
actor=cls.actor)
|
||||
readfield = cls._checkedRead(f.ipdltype,
|
||||
ExprAddrOf(get('->', f)), f.basename,
|
||||
'\'' + f.getMethod().name + '\' ' +
|
||||
'(' + f.ipdltype.name() + ') member of ' +
|
||||
'\'' + structtype.name() + '\'')
|
||||
for (size, fields) in itertools.groupby(sd.fields_member_order(),
|
||||
lambda f: pod_size(f.ipdltype)):
|
||||
fields = list(fields)
|
||||
|
||||
# Wrap the read/write in a side check if the field is special.
|
||||
if f.special:
|
||||
writefield = cls.ifsideis(f.side, writefield)
|
||||
readfield = cls.ifsideis(f.side, readfield)
|
||||
if size == pod_size_sentinel:
|
||||
for f in fields:
|
||||
writefield = cls.checkedWrite(f.ipdltype,
|
||||
get('.', f),
|
||||
cls.msgvar,
|
||||
sentinelKey=f.basename,
|
||||
actor=cls.actor)
|
||||
readfield = cls._checkedRead(f.ipdltype,
|
||||
ExprAddrOf(get('->', f)), f.basename,
|
||||
'\'' + f.getMethod().name + '\' ' +
|
||||
'(' + f.ipdltype.name() + ') member of ' +
|
||||
'\'' + structtype.name() + '\'')
|
||||
|
||||
write.append(writefield)
|
||||
read.append(readfield)
|
||||
# Wrap the read/write in a side check if the field is special.
|
||||
if f.special:
|
||||
writefield = cls.ifsideis(f.side, writefield)
|
||||
readfield = cls.ifsideis(f.side, readfield)
|
||||
|
||||
write.append(writefield)
|
||||
read.append(readfield)
|
||||
else:
|
||||
for f in fields:
|
||||
assert not f.special
|
||||
|
||||
writefield = cls.checkedBulkWrite(size, fields)
|
||||
readfield = cls.checkedBulkRead(size, fields)
|
||||
|
||||
write.append(writefield)
|
||||
read.append(readfield)
|
||||
|
||||
read.append(StmtReturn.TRUE)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user