Bug 1323532 - Part 2 - don't codegen Transition functions in ipdl, just statically define the two variants we need; r?froydnj
MozReview-Commit-ID: GdATc0Wdsxi
--- a/ipc/glue/ProtocolUtils.cpp
+++ b/ipc/glue/ProtocolUtils.cpp
@@ -350,16 +350,59 @@ ArrayLengthReadError(const char* aElemen
void
SentinelReadError(const char* aClassName)
{
MOZ_CRASH_UNSAFE_PRINTF("incorrect sentinel when reading %s", aClassName);
}
void
+StateTransition(bool aIsDelete, State* aNext)
+{
+ switch (*aNext) {
+ case State::Null:
+ if (aIsDelete) {
+ *aNext = State::Dead;
+ }
+ break;
+ case State::Dead:
+ LogicError("__delete__()d actor");
+ break;
+ default:
+ LogicError("corrupted actor state");
+ break;
+ }
+}
+
+void
+ReEntrantDeleteStateTransition(bool aIsDelete,
+ bool aIsDeleteReply,
+ ReEntrantDeleteState* aNext)
+{
+ switch (*aNext) {
+ case ReEntrantDeleteState::Null:
+ if (aIsDelete) {
+ *aNext = ReEntrantDeleteState::Dying;
+ }
+ break;
+ case ReEntrantDeleteState::Dead:
+ LogicError("__delete__()d actor");
+ break;
+ case ReEntrantDeleteState::Dying:
+ if (aIsDeleteReply) {
+ *aNext = ReEntrantDeleteState::Dead;
+ }
+ break;
+ default:
+ LogicError("corrupted actor state");
+ break;
+ }
+}
+
+void
TableToArray(const nsTHashtable<nsPtrHashKey<void>>& aTable,
nsTArray<void*>& aArray)
{
uint32_t i = 0;
void** elements = aArray.AppendElements(aTable.Count());
for (auto iter = aTable.ConstIter(); !iter.Done(); iter.Next()) {
elements[i] = iter.Get()->GetKey();
++i;
--- a/ipc/glue/ProtocolUtils.h
+++ b/ipc/glue/ProtocolUtils.h
@@ -126,28 +126,16 @@ 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,
@@ -757,16 +745,39 @@ DuplicateHandle(HANDLE aSourceHandle,
#endif
/**
* Annotate the crash reporter with the error code from the most recent system
* call. Returns the system error.
*/
void AnnotateSystemError();
+enum class State
+{
+ Dead,
+ Null,
+ Start = Null
+};
+
+void
+StateTransition(bool aIsDelete, State* aNext);
+
+enum class ReEntrantDeleteState
+{
+ Dead,
+ Null,
+ Dying,
+ Start = Null,
+};
+
+void
+ReEntrantDeleteStateTransition(bool aIsDelete,
+ bool aIsDeleteReply,
+ ReEntrantDeleteState* aNext);
+
/**
* An endpoint represents one end of a partially initialized IPDL channel. To
* set up a new top-level protocol:
*
* Endpoint<PFooParent> parentEp;
* Endpoint<PFooChild> childEp;
* nsresult rv;
* rv = PFoo::CreateEndpoints(parentPid, childPid, &parentEp, &childEp);
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -1565,20 +1565,16 @@ class _GenerateProtocolCode(ipdl.ast.Vis
edecl, edefn = _splitFuncDeclDefn(self.genEndpointFunc())
ns.addstmts([ edecl, Whitespace.NL ])
self.funcDefns.append(edefn)
# 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)
-
for md in p.messageDecls:
decls = []
# Look up the segment capacity used for serializing this
# message. If the capacity is not specified, use '0' for
# the default capacity (defined in ipc_message.cc)
name = '%s::%s' % (md.namespace, md.decl.progname)
segmentcapacity = self.segmentcapacitydict.get(name, 0)
@@ -1624,72 +1620,16 @@ class _GenerateProtocolCode(ipdl.ast.Vis
ExprVar('mozilla::ipc::CreateEndpoints'),
args=[ _backstagePass(),
parentpidvar, childpidvar,
parentvar, childvar
])))
return openfunc
- def genTransitionFunc(self):
- ptype = self.protocol.decl.type
-
- # 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(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 = self.protocol.dyingState()
- else:
- nextState = self.protocol.deadState()
- ifdelete.addifstmt(
- StmtExpr(ExprAssn(ExprDeref(nextvar), nextState)))
- nullerrorblock.addstmt(ifdelete)
- nullerrorblock.addstmt(StmtBreak())
- fromswitch.addcase(CaseLabel(self.protocol.nullState().name), nullerrorblock)
-
- # special case for Dead
- deadblock = Block()
- deadblock.addstmts([
- _logicError('__delete__()d actor'),
- StmtBreak() ])
- 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), self.protocol.deadState())))
- dyingblock.addstmt(ifdelete)
- dyingblock.addstmt(StmtBreak())
- fromswitch.addcase(CaseLabel(self.protocol.dyingState().name), dyingblock)
-
- unreachedblock = Block()
- unreachedblock.addstmts([
- _logicError('corrupted actor state'),
- StmtBreak() ])
- fromswitch.addcase(DefaultLabel(), unreachedblock)
-
- transitionfunc.addstmt(fromswitch)
-
- return transitionfunc
##--------------------------------------------------
def _generateMessageConstructor(md, segmentSize, protocol, forReply=False):
if forReply:
clsname = md.replyCtorFunc()
msgid = md.replyId()
replyEnum = 'REPLY'
@@ -4683,23 +4623,38 @@ class _GenerateProtocolActorCode(ipdl.as
# avoid unused-variable warnings
saveIdStmts = [ StmtDecl(Decl(_actorIdType(), idvar.name),
self.protocol.routingId()) ]
else:
saveIdStmts = [ ]
return idvar, saveIdStmts
def transition(self, md, actor=None, reply=False):
- if actor is not None: stateexpr = _actorState(actor)
- else: stateexpr = self.protocol.stateVar()
-
msgid = md.pqMsgId() if not reply else md.pqReplyId()
- return [ StmtExpr(ExprCall(ExprVar(self.protocol.name +'::Transition'),
- args=[ ExprVar(msgid),
- ExprAddrOf(stateexpr) ])) ]
+ args = [
+ ExprVar('true' if _deleteId().name == msgid else 'false'),
+ ]
+ if self.protocol.decl.type.hasReentrantDelete:
+ function = 'ReEntrantDeleteStateTransition'
+ args.append(
+ ExprVar('true' if _deleteReplyId().name == msgid else 'false'),
+ )
+ else:
+ function = 'StateTransition'
+
+ if actor is not None:
+ stateexpr = _actorState(actor)
+ else:
+ stateexpr = self.protocol.stateVar()
+
+ args.append(ExprAddrOf(stateexpr))
+
+ return [
+ StmtExpr(ExprCall(ExprVar(function), args=args))
+ ]
def endRead(self, msgexpr, iterexpr):
msgtype = ExprCall(ExprSelect(msgexpr, '.', 'type'), [ ])
return StmtExpr(ExprCall(ExprSelect(msgexpr, '.', 'EndRead'),
args=[ iterexpr, msgtype ]))
class _GenerateProtocolParentCode(_GenerateProtocolActorCode):
def __init__(self):