зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1431867
- Part 1: Remove some unnecessary complexity from generated IPDL structs, r=mccr8
MozReview-Commit-ID: HvX4ZF8t9Eg
This commit is contained in:
Родитель
c55a15b2ef
Коммит
a1e4513e2a
|
@ -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
|
||||
|
||||
##-----------------------------------------------------------------------------
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче