Bug 1323532 - Part 1 - don't codegen State enums in ipdl, just statically define the two types we need; r=froydnj
authorAlex Gaynor <agaynor@mozilla.com>
Mon, 30 Apr 2018 15:22:18 -0400
changeset 472529 4c6d8b9e3b3b4fd3a7a019489b7d781bcda9c5f5
parent 472528 db8dd9bc2e5cc5c61b7d329481b7b25eb5b10ef8
child 472530 e8097237f4be577ec43a6c03669d57de7a221b5b
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1323532
milestone61.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 1323532 - Part 1 - don't codegen State enums in ipdl, just statically define the two types we need; r=froydnj MozReview-Commit-ID: CSfCBiQnKxZ
ipc/glue/ProtocolUtils.h
ipc/ipdl/ipdl/lower.py
--- a/ipc/glue/ProtocolUtils.h
+++ b/ipc/glue/ProtocolUtils.h
@@ -126,16 +126,29 @@ struct ActorHandle
 
 // What happens if Interrupt calls race?
 enum RacyInterruptPolicy {
     RIPError,
     RIPChildWins,
     RIPParentWins
 };
 
+enum class State {
+    Dead,
+    Null,
+    Start = Null
+};
+
+enum class ReEntrantDeleteState {
+    Dead,
+    Null,
+    Dying,
+    Start = Null,
+};
+
 class IToplevelProtocol;
 
 class IProtocol : public HasResultCodes
 {
 public:
     enum ActorDestroyReason {
         FailedConstructor,
         Deletion,
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -133,38 +133,16 @@ def _actorState(actor):
     return ExprSelect(actor, '->', 'mState')
 
 def _backstagePass():
     return ExprCall(ExprVar('mozilla::ipc::PrivateIPDLInterface'))
 
 def _iterType(ptr):
     return Type('PickleIterator', ptr=ptr)
 
-def _nullState(proto=None):
-    pfx = ''
-    if proto is not None:  pfx = proto.name() +'::'
-    return ExprVar(pfx +'__Null')
-
-def _deadState(proto=None):
-    pfx = ''
-    if proto is not None:  pfx = proto.name() +'::'
-    return ExprVar(pfx +'__Dead')
-
-def _dyingState(proto=None):
-    pfx = ''
-    if proto is not None:  pfx = proto.name() +'::'
-    return ExprVar(pfx +'__Dying')
-
-def _startState(proto=None, fq=False):
-    pfx = ''
-    if proto:
-        if fq:  pfx = proto.fullname() +'::'
-        else:   pfx = proto.name() +'::'
-    return ExprVar(pfx +'__Start')
-
 def _deleteId():
     return ExprVar('Msg___delete____ID')
 
 def _deleteReplyId():
     return ExprVar('Reply___delete____ID')
 
 def _lookupListener(idexpr):
     return ExprCall(ExprVar('Lookup'), args=[ idexpr ])
@@ -1072,16 +1050,27 @@ def _subtreeUsesShmem(p):
 
     ptype = p.decl.type
     for mgd in ptype.manages:
         if ptype is not mgd:
             if _subtreeUsesShmem(mgd._ast):
                 return True
     return False
 
+def _stateType(hasReentrantDelete):
+    if hasReentrantDelete:
+        return Type('mozilla::ipc::ReEntrantDeleteState')
+    else:
+        return Type('mozilla::ipc::State')
+
+def _startState(hasReentrantDelete):
+    pfx = _stateType(hasReentrantDelete).name + '::'
+    return ExprVar(pfx + 'Start')
+
+
 class Protocol(ipdl.ast.Protocol):
     def cxxTypedefs(self):
         return self.decl.cxxtypedefs
 
     def channelSel(self):
         if self.decl.type.isToplevel():  return '.'
         return '->'
 
@@ -1192,26 +1181,33 @@ class Protocol(ipdl.ast.Protocol):
         return ExprCall(ExprVar('Id'))
 
     def stateVar(self, actorThis=None):
         if actorThis is not None:
             return ExprSelect(actorThis, '->', 'mState')
         return ExprVar('mState')
 
     def fqStateType(self):
-        return Type(self.decl.type.name() +'::State')
+        return _stateType(self.decl.type.hasReentrantDelete)
 
     def startState(self):
-        return _startState(self.decl.type)
+        return _startState(self.decl.type.hasReentrantDelete)
 
     def nullState(self):
-        return _nullState(self.decl.type)
+        pfx = self.fqStateType().name + '::'
+        return ExprVar(pfx + 'Null')
 
     def deadState(self):
-        return _deadState(self.decl.type)
+        pfx = self.fqStateType().name + '::'
+        return ExprVar(pfx + 'Dead')
+
+    def dyingState(self):
+        assert self.decl.type.hasReentrantDelete
+        pfx = self.fqStateType().name + '::'
+        return ExprVar(pfx + 'Dying')
 
     def managerVar(self, thisexpr=None):
         assert thisexpr is not None or not self.decl.type.isToplevel()
         mvar = ExprCall(ExprVar('Manager'), args=[])
         if thisexpr is not None:
             mvar = ExprCall(ExprSelect(thisexpr, '->', 'Manager'), args=[])
         return mvar
 
@@ -1565,28 +1561,16 @@ class _GenerateProtocolCode(ipdl.ast.Vis
         ns = Namespace(self.protocol.name)
         self.hdrfile.addthing(_putInNamespaces(ns, p.namespaces))
         ns.addstmt(Whitespace.NL)
 
         edecl, edefn = _splitFuncDeclDefn(self.genEndpointFunc())
         ns.addstmts([ edecl, Whitespace.NL ])
         self.funcDefns.append(edefn)
 
-        # state information
-        stateenum = TypeEnum('State')
-        # NB: __Dead is the first state on purpose, so that it has
-        # value '0'
-        stateenum.addId(_deadState().name)
-        stateenum.addId(_nullState().name)
-        if self.protocol.decl.type.hasReentrantDelete:
-            stateenum.addId(_dyingState().name)
-        stateenum.addId(_startState().name, _nullState().name)
-
-        ns.addstmts([ StmtDecl(Decl(stateenum,'')), Whitespace.NL ])
-
         # spit out message type enum and classes
         msgenum = msgenums(self.protocol)
         ns.addstmts([ StmtDecl(Decl(msgenum, '')), Whitespace.NL ])
 
         tfDecl, tfDefn = _splitFuncDeclDefn(self.genTransitionFunc())
         ns.addstmts([ tfDecl, Whitespace.NL ])
         self.funcDefns.append(tfDefn)
 
@@ -1651,51 +1635,51 @@ class _GenerateProtocolCode(ipdl.ast.Vis
         # bool Transition(MessageType msg, State* next)
         # The state we are transitioning from is stored in *next.
         msgtypevar = ExprVar('msg')
         nextvar = ExprVar('next')
 
         transitionfunc = FunctionDefn(FunctionDecl(
             'Transition',
             params=[ Decl(Type('MessageType'), msgtypevar.name),
-                     Decl(Type('State', ptr=1), nextvar.name) ],
+                     Decl(Type(self.protocol.fqStateType().name, ptr=1), nextvar.name) ],
             ret=Type.VOID))
 
         fromswitch = StmtSwitch(ExprDeref(nextvar))
 
         # special case for Null
         nullerrorblock = Block()
         if ptype.hasDelete:
             ifdelete = StmtIf(ExprBinary(_deleteId(), '==', msgtypevar))
             if ptype.hasReentrantDelete:
-                nextState = _dyingState()
+                nextState = self.protocol.dyingState()
             else:
-                nextState = _deadState()
+                nextState = self.protocol.deadState()
             ifdelete.addifstmt(
                 StmtExpr(ExprAssn(ExprDeref(nextvar), nextState)))
             nullerrorblock.addstmt(ifdelete)
         nullerrorblock.addstmt(StmtBreak())
-        fromswitch.addcase(CaseLabel(_nullState().name), nullerrorblock)
+        fromswitch.addcase(CaseLabel(self.protocol.nullState().name), nullerrorblock)
 
         # special case for Dead
         deadblock = Block()
         deadblock.addstmts([
             _logicError('__delete__()d actor'),
             StmtBreak() ])
-        fromswitch.addcase(CaseLabel(_deadState().name), deadblock)
+        fromswitch.addcase(CaseLabel(self.protocol.deadState().name), deadblock)
 
         # special case for Dying
         if ptype.hasReentrantDelete:
             dyingblock = Block()
             ifdelete = StmtIf(ExprBinary(_deleteReplyId(), '==', msgtypevar))
             ifdelete.addifstmt(
-                StmtExpr(ExprAssn(ExprDeref(nextvar), _deadState())))
+                StmtExpr(ExprAssn(ExprDeref(nextvar), self.protocol.deadState())))
             dyingblock.addstmt(ifdelete)
             dyingblock.addstmt(StmtBreak())
-            fromswitch.addcase(CaseLabel(_dyingState().name), dyingblock)
+            fromswitch.addcase(CaseLabel(self.protocol.dyingState().name), dyingblock)
 
         unreachedblock = Block()
         unreachedblock.addstmts([
             _logicError('corrupted actor state'),
             StmtBreak() ])
         fromswitch.addcase(DefaultLabel(), unreachedblock)
 
         transitionfunc.addstmt(fromswitch)
@@ -3056,16 +3040,19 @@ class _GenerateProtocolActorCode(ipdl.as
 
         # FIXME: all actors impl Iface for now
         if ptype.isManager() or 1:
             self.hdrfile.addthing(CppDirective('include', '"base/id_map.h"'))
 
         self.hdrfile.addthings([
             CppDirective('include', '"mozilla/ipc/MessageChannel.h"'),
             Whitespace.NL ])
+        self.hdrfile.addthings([
+            CppDirective('include', '"mozilla/ipc/ProtocolUtils.h"'),
+            Whitespace.NL ])
 
         hasAsyncReturns = False
         for md in p.messageDecls:
             if md.hasAsyncReturns():
                 hasAsyncReturns = True
                 break
 
         inherits = []
@@ -3122,18 +3109,16 @@ class _GenerateProtocolActorCode(ipdl.as
         self.cls.addstmt(Label.PROTECTED)
         for typedef in p.cxxTypedefs():
             self.cls.addstmt(typedef)
         for typedef in self.includedActorTypedefs:
             self.cls.addstmt(typedef)
 
         self.cls.addstmt(Whitespace.NL)
 
-        self.cls.addstmts([ Typedef(p.fqStateType(), 'State'), Whitespace.NL ])
-
         if hasAsyncReturns:
             self.cls.addstmt(Label.PUBLIC)
             for md in p.messageDecls:
                 if self.sendsMessage(md) and md.hasAsyncReturns():
                     self.cls.addstmt(
                         Typedef(_makePromise(md.returns, self.side),
                                 md.promiseName()))
                 if self.receivesMessage(md) and md.hasAsyncReturns():
@@ -3395,17 +3380,17 @@ class _GenerateProtocolActorCode(ipdl.as
 
                 method.addstmts([ routedecl, routeif, Whitespace.NL ])
 
             # in the event of an Interrupt delete message, we want to loudly complain about
             # messages that are received that are not a reply to the original message
             if ptype.hasReentrantDelete:
                 msgVar = ExprVar(params[0].name)
                 ifdying = StmtIf(ExprBinary(
-                    ExprBinary(ExprVar('mState'), '==', _dyingState(ptype)),
+                    ExprBinary(ExprVar('mState'), '==', self.protocol.dyingState()),
                     '&&',
                     ExprBinary(
                         ExprBinary(ExprCall(ExprSelect(msgVar, '.', 'is_reply')), '!=', ExprLiteral.TRUE),
                         '||',
                         ExprBinary(ExprCall(ExprSelect(msgVar, '.', 'is_interrupt')), '!=', ExprLiteral.TRUE))))
                 ifdying.addifstmts([_fatalError('incoming message racing with actor deletion'),
                                     StmtReturn(_Result.Processed)])
                 method.addstmt(ifdying)
@@ -3614,17 +3599,17 @@ class _GenerateProtocolActorCode(ipdl.as
         # we're toplevel
         self.cls.addstmts([ deallocsubtree, Whitespace.NL ])
 
         if ptype.isToplevel():
             deallocself = MethodDefn(MethodDecl(deallocselfvar.name, methodspec=MethodSpec.VIRTUAL))
             self.cls.addstmts([ deallocself, Whitespace.NL ])
 
         ## private members
-        self.cls.addstmt(StmtDecl(Decl(Type('State'), p.stateVar().name)))
+        self.cls.addstmt(StmtDecl(Decl(self.protocol.fqStateType(), p.stateVar().name)))
 
         for managed in ptype.manages:
             self.cls.addstmts([
                 StmtDecl(Decl(
                     p.managedVarType(managed, self.side),
                     p.managedVar(managed, self.side).name)) ])
 
     def implementManagerIface(self):
@@ -3897,17 +3882,17 @@ class _GenerateProtocolActorCode(ipdl.as
         return [
             self.failIfNullActor(actorvar, errfn, msg="Error constructing actor %s" % actortype.name() + self.side.capitalize()),
             StmtExpr(setmanager),
             StmtExpr(_callInsertManagedActor(
                 self.protocol.managedVar(md.decl.type.constructedType(),
                                          self.side),
                 actorvar)),
             StmtExpr(ExprAssn(_actorState(actorvar),
-                              _startState(actorproto, fq=1)))
+                              _startState(md.decl.type.cdtype.hasReentrantDelete)))
         ]
 
     def failCtorIf(self, md, cond):
         actorvar = md.actorDecl().var()
         type = md.decl.type.constructedType()
         failif = StmtIf(cond)
 
         if self.side=='child':