Bug 1431867 - Part 1: Remove some unnecessary complexity from generated IPDL structs, r=mccr8

MozReview-Commit-ID: HvX4ZF8t9Eg
This commit is contained in:
Nika Layzell 2018-01-18 18:18:28 -05:00
Родитель c55a15b2ef
Коммит a1e4513e2a
2 изменённых файлов: 99 добавлений и 106 удалений

Просмотреть файл

@ -68,6 +68,12 @@ struct null_t {
struct SerializedStructuredCloneBuffer final
{
SerializedStructuredCloneBuffer() {}
SerializedStructuredCloneBuffer(const SerializedStructuredCloneBuffer& aOther)
{
*this = aOther;
}
SerializedStructuredCloneBuffer&
operator=(const SerializedStructuredCloneBuffer& aOther)
{

Просмотреть файл

@ -9,7 +9,7 @@ from collections import OrderedDict
import ipdl.ast
import ipdl.builtin
from ipdl.cxx.ast import *
from ipdl.type import ActorType, TypeVisitor, builtinHeaderIncludes
from ipdl.type import ActorType, UnionType, TypeVisitor, builtinHeaderIncludes
##-----------------------------------------------------------------------------
## "Public" interface to lowering
@ -708,13 +708,6 @@ class _CompoundTypeComponent(_HybridDecl):
_HybridDecl.__init__(self, ipdltype, name)
self.side = side
self.special = _hasVisibleActor(ipdltype)
self.recursive = ct.decl.type.mutuallyRecursiveWith(ipdltype)
def internalType(self):
if self.recursive:
return self.ptrToType()
else:
return self.bareType()
# @override the following methods to pass |self.side| instead of
# forcing the caller to remember which side we're declared to
@ -765,8 +758,6 @@ class _StructField(_CompoundTypeComponent):
ref = self.memberVar()
if thisexpr is not None:
ref = ExprSelect(thisexpr, '.', ref.name)
if self.recursive:
ref = ExprDeref(ref)
return ref
def constRefExpr(self, thisexpr=None):
@ -786,22 +777,6 @@ class _StructField(_CompoundTypeComponent):
def memberVar(self):
return ExprVar(self.name + '_')
def initStmts(self):
if self.recursive:
return [ StmtExpr(ExprAssn(self.memberVar(),
ExprNew(self.bareType()))) ]
elif self.ipdltype.isIPDL() and self.ipdltype.isActor():
return [ StmtExpr(ExprAssn(self.memberVar(),
ExprLiteral.NULL)) ]
else:
return []
def destructStmts(self):
if self.recursive:
return [ StmtExpr(ExprDelete(self.memberVar())) ]
else:
return []
class UnionDecl(ipdl.ast.UnionDecl, HasFQName):
def callType(self, var=None):
@ -833,6 +808,11 @@ IPDL union type."""
else:
self.other = _UnionMember(ipdltype, ud, _otherSide(side), self)
# To create a finite object with a mutually recursive type, a union must
# be present somewhere in the recursive loop. Because of that we only
# need to care about introducing indirections inside unions.
self.recursive = ud.decl.type.mutuallyRecursiveWith(ipdltype)
def enum(self):
return 'T' + self.flattypename
@ -842,6 +822,12 @@ IPDL union type."""
def enumvar(self):
return ExprVar(self.enum())
def internalType(self):
if self.recursive:
return self.ptrToType()
else:
return self.bareType()
def unionType(self):
"""Type used for storage in generated C union decl."""
if self.recursive:
@ -1488,7 +1474,20 @@ class _GenerateProtocolCode(ipdl.ast.Visitor):
for headername in sorted(iter(aggregateTypeIncludes)):
hf.addthing(CppDirective('include', '"' + headername + '"'))
ipdl.ast.Visitor.visitTranslationUnit(self, tu)
# Manually run Visitor.visitTranslationUnit. For dependency resolution
# we need to handle structs and unions separately.
for cxxInc in tu.cxxIncludes:
cxxInc.accept(self)
for inc in tu.includes:
inc.accept(self)
self.generateStructsAndUnions(tu)
for using in tu.builtinUsing:
using.accept(self)
for using in tu.using:
using.accept(self)
if tu.protocol:
tu.protocol.accept(self)
if tu.filetype == 'header':
self.cppIncludeHeaders.append(_ipdlhHeaderName(tu))
@ -1522,36 +1521,56 @@ class _GenerateProtocolCode(ipdl.ast.Visitor):
self.hdrfile.addthing(CppDirective(
'include', '"'+ _ipdlhHeaderName(inc.tu) +'.h"'))
def processStructOrUnionClass(self, su, which, forwarddecls, cls):
clsdecl, methoddefns = _splitClassDeclDefn(cls)
def generateStructsAndUnions(self, tu):
'''Generate the definitions for all structs and unions. This will
re-order the declarations if needed in the C++ code such that
dependencies have already been defined.'''
decls = OrderedDict()
for su in tu.structsAndUnions:
if isinstance(su, StructDecl):
which = 'struct'
forwarddecls, fulldecltypes, cls = _generateCxxStruct(su)
else:
assert isinstance(su, UnionDecl)
which = 'union'
forwarddecls, fulldecltypes, cls = _generateCxxUnion(su)
self.hdrfile.addthings(
[ Whitespace.NL ]
+ forwarddecls
+ [ Whitespace("""
clsdecl, methoddefns = _splitClassDeclDefn(cls)
# Store the declarations in the decls map so we can emit in
# dependency order.
decls[su.decl.type] = (
fulldecltypes,
[ Whitespace.NL ]
+ forwarddecls
+ [ Whitespace("""
//-----------------------------------------------------------------------------
// Declaration of the IPDL type |%s %s|
//
"""% (which, su.name)),
_putInNamespaces(clsdecl, su.namespaces),
])
_putInNamespaces(clsdecl, su.namespaces),
])
self.structUnionDefns.extend([
Whitespace("""
self.structUnionDefns.extend([
Whitespace("""
//-----------------------------------------------------------------------------
// Method definitions for the IPDL type |%s %s|
//
"""% (which, su.name)),
_putInNamespaces(methoddefns, su.namespaces),
])
_putInNamespaces(methoddefns, su.namespaces),
])
def visitStructDecl(self, sd):
return self.processStructOrUnionClass(sd, 'struct',
*_generateCxxStruct(sd))
def visitUnionDecl(self, ud):
return self.processStructOrUnionClass(ud, 'union',
*_generateCxxUnion(ud))
# Generate the declarations structs in dependency order.
def gen_struct(deps, defn):
for dep in deps:
if dep in decls:
d, t = decls[dep]
del decls[dep]
gen_struct(d, t)
self.hdrfile.addthings(defn)
while len(decls) > 0:
_, (d, t) = decls.popitem(False)
gen_struct(d, t)
def visitProtocol(self, p):
self.cppIncludeHeaders.append(_protocolHeaderName(self.protocol, ''))
@ -1806,14 +1825,16 @@ def _generateMessageConstructor(md, segmentSize, protocol, forReply=False):
class _ComputeTypeDeps(TypeVisitor):
'''Pass that gathers the C++ types that a particular IPDL type
(recursively) depends on. There are two kinds of dependencies: (i)
(recursively) depends on. There are three kinds of dependencies: (i)
types that need forward declaration; (ii) types that need a |using|
stmt. Some types generate both kinds.'''
stmt; (iii) IPDL structs or unions which must be fully declared
before this struct. Some types generate multiple kinds.'''
def __init__(self, fortype, unqualifiedTypedefs=False):
ipdl.type.TypeVisitor.__init__(self)
self.usingTypedefs = [ ]
self.forwardDeclStmts = [ ]
self.fullDeclTypes = [ ]
self.fortype = fortype
self.unqualifiedTypedefs = unqualifiedTypedefs
@ -1847,8 +1868,12 @@ stmt. Some types generate both kinds.'''
self.visited.add(su)
self.maybeTypedef(su.fullname(), su.name())
if su.mutuallyRecursiveWith(self.fortype):
# Mutually recursive fields in unions are behind indirection, so we only
# need a forward decl, and don't need a full type declaration.
if isinstance(self.fortype, UnionType) and self.fortype.mutuallyRecursiveWith(su):
self.forwardDeclStmts.append(_makeForwardDecl(su))
else:
self.fullDeclTypes.append(su)
return defaultVisit(self, su)
@ -1891,6 +1916,7 @@ def _generateCxxStruct(sd):
usingTypedefs = gettypedeps.usingTypedefs
forwarddeclstmts = gettypedeps.forwardDeclStmts
fulldecltypes = gettypedeps.fullDeclTypes
struct = Class(sd.name, final=1)
struct.addstmts([ Label.PRIVATE ]
@ -1898,9 +1924,6 @@ def _generateCxxStruct(sd):
+ [ Whitespace.NL, Label.PUBLIC ])
constreftype = Type(sd.name, const=1, ref=1)
initvar = ExprVar('Init')
callinit = ExprCall(initvar)
assignvar = ExprVar('Assign')
def fieldsAsParamList():
return [ Decl(f.inType(), f.argVar().name) for f in sd.fields ]
@ -1914,54 +1937,30 @@ def _generateCxxStruct(sd):
# with the default ctor.
if len(sd.fields):
# Struct()
defctor = ConstructorDefn(ConstructorDecl(sd.name))
defctor.addstmt(StmtExpr(callinit))
defctor.memberinits = []
for f in sd.fields:
# Only generate default values for primitives.
if not (f.ipdltype.isCxx() and f.ipdltype.isAtom()):
continue
defctor.memberinits.append(ExprMemberInit(f.memberVar()))
defctor = ConstructorDefn(ConstructorDecl(sd.name, force_inline=1))
# We want to explicitly default-construct every member of the struct.
# This will initialize all primitives which wouldn't be initialized
# normally to their default values, and will initialize any actor member
# pointers to the correct default value of `nullptr`. Other C++ types
# with custom constructors must also provide a default constructor.
defctor.memberinits = [ ExprMemberInit(f.memberVar()) for f in sd.fields ]
struct.addstmts([ defctor, Whitespace.NL ])
# Struct(const field1& _f1, ...)
valctor = ConstructorDefn(ConstructorDecl(sd.name,
params=fieldsAsParamList(),
force_inline=1))
valctor.addstmts([
StmtExpr(callinit),
StmtExpr(ExprCall(assignvar,
args=[ f.argVar() for f in sd.fields ]))
])
valctor.memberinits = [ ExprMemberInit(f.memberVar(),
args=[ f.argVar() ])
for f in sd.fields ]
struct.addstmts([ valctor, Whitespace.NL ])
# Struct(const Struct& _o)
ovar = ExprVar('_o')
copyctor = ConstructorDefn(ConstructorDecl(
sd.name,
params=[ Decl(constreftype, ovar.name) ],
force_inline=1))
copyctor.addstmts([
StmtExpr(callinit),
StmtExpr(assignFromOther(ovar))
])
struct.addstmts([ copyctor, Whitespace.NL ])
# ~Struct()
dtor = DestructorDefn(DestructorDecl(sd.name))
for f in sd.fields:
dtor.addstmts(f.destructStmts())
struct.addstmts([ dtor, Whitespace.NL ])
# Struct& operator=(const Struct& _o)
opeq = MethodDefn(MethodDecl(
'operator=',
params=[ Decl(constreftype, ovar.name) ],
force_inline=1))
opeq.addstmt(StmtExpr(assignFromOther(ovar)))
struct.addstmts([ opeq, Whitespace.NL ])
# The default copy, move, and assignment constructors, and the default
# destructor, will do the right thing.
# bool operator==(const Struct& _o)
ovar = ExprVar('_o')
opeqeq = MethodDefn(MethodDecl(
'operator==',
params=[ Decl(constreftype, ovar.name) ],
@ -2006,24 +2005,11 @@ def _generateCxxStruct(sd):
# private:
struct.addstmt(Label.PRIVATE)
# Init()
init = MethodDefn(MethodDecl(initvar.name))
for f in sd.fields:
init.addstmts(f.initStmts())
struct.addstmts([ init, Whitespace.NL ])
# Assign(const field1& _f1, ...)
assign = MethodDefn(MethodDecl(assignvar.name,
params=fieldsAsParamList()))
assign.addstmts([ StmtExpr(ExprAssn(f.refExpr(), f.argVar()))
for f in sd.fields ])
struct.addstmts([ assign, Whitespace.NL ])
# members
struct.addstmts([ StmtDecl(Decl(f.internalType(), f.memberVar().name))
struct.addstmts([ StmtDecl(Decl(f.bareType(), f.memberVar().name))
for f in sd.fields ])
return forwarddeclstmts, struct
return forwarddeclstmts, fulldecltypes, struct
##--------------------------------------------------
@ -2100,6 +2086,7 @@ def _generateCxxUnion(ud):
usingTypedefs = gettypedeps.usingTypedefs
forwarddeclstmts = gettypedeps.forwardDeclStmts
fulldecltypes = gettypedeps.fullDeclTypes
# the |Type| enum, used to switch on the discunion's real type
cls.addstmt(Label.PUBLIC)
@ -2397,7 +2384,7 @@ def _generateCxxUnion(ud):
StmtDecl(Decl(typetype, mtypevar.name))
])
return forwarddeclstmts, cls
return forwarddeclstmts, fulldecltypes, cls
##-----------------------------------------------------------------------------