Bug 1316755, part 3 - Remove bridges, opens and spawns from IPDL. draft
authorAndrew McCreight <continuation@gmail.com>
Thu, 26 Jan 2017 16:43:27 -0800
changeset 467556 bcc0f737b704e83d3a02e8c480bf2f11ff2c5ceb
parent 467555 53be4b927dc1047822ed3b7f4fe2c31de661522e
child 543723 daa36d569422d52b3520cf58098ee064e0f98b36
push id43218
push userbmo:continuation@gmail.com
push dateSat, 28 Jan 2017 00:54:33 +0000
bugs1316755
milestone54.0a1
Bug 1316755, part 3 - Remove bridges, opens and spawns from IPDL. MozReview-Commit-ID: 2BDEXV0r8QB
ipc/ipdl/ipdl/ast.py
ipc/ipdl/ipdl/lower.py
ipc/ipdl/ipdl/parser.py
ipc/ipdl/ipdl/type.py
--- a/ipc/ipdl/ipdl/ast.py
+++ b/ipc/ipdl/ipdl/ast.py
@@ -51,41 +51,26 @@ class Visitor:
             t.accept(self)
 
     def visitUsingStmt(self, using):
         pass
 
     def visitProtocol(self, p):
         for namespace in p.namespaces:
             namespace.accept(self)
-        for spawns in p.spawnsStmts:
-            spawns.accept(self)
-        for bridges in p.bridgesStmts:
-            bridges.accept(self)
-        for opens in p.opensStmts:
-            opens.accept(self)
         for mgr in p.managers:
             mgr.accept(self)
         for managed in p.managesStmts:
             managed.accept(self)
         for msgDecl in p.messageDecls:
             msgDecl.accept(self)
 
     def visitNamespace(self, ns):
         pass
 
-    def visitSpawnsStmt(self, spawns):
-        pass
-
-    def visitBridgesStmt(self, bridges):
-        pass
-
-    def visitOpensStmt(self, opens):
-        pass
-
     def visitManager(self, mgr):
         pass
 
     def visitManagesStmt(self, mgs):
         pass
 
     def visitMessageDecl(self, md):
         for inParam in md.inParams:
@@ -221,19 +206,16 @@ class Namespace(Node):
         Node.__init__(self, loc)
         self.name = namespace
 
 class Protocol(NamespacedNode):
     def __init__(self, loc):
         NamespacedNode.__init__(self, loc)
         self.sendSemantics = ASYNC
         self.nested = NOT_NESTED
-        self.spawnsStmts = [ ]
-        self.bridgesStmts = [ ]
-        self.opensStmts = [ ]
         self.managers = [ ]
         self.managesStmts = [ ]
         self.messageDecls = [ ]
 
 class StructField(Node):
     def __init__(self, loc, type, name):
         Node.__init__(self, loc)
         self.typespec = type
@@ -244,35 +226,16 @@ class StructDecl(NamespacedNode):
         NamespacedNode.__init__(self, loc, name)
         self.fields = fields
 
 class UnionDecl(NamespacedNode):
     def __init__(self, loc, name, components):
         NamespacedNode.__init__(self, loc, name)
         self.components = components
 
-class SpawnsStmt(Node):
-    def __init__(self, loc, side, proto, spawnedAs):
-        Node.__init__(self, loc)
-        self.side = side
-        self.proto = proto
-        self.spawnedAs = spawnedAs
-
-class BridgesStmt(Node):
-    def __init__(self, loc, parentSide, childSide):
-        Node.__init__(self, loc)
-        self.parentSide = parentSide
-        self.childSide = childSide
-
-class OpensStmt(Node):
-    def __init__(self, loc, side, proto):
-        Node.__init__(self, loc)
-        self.side = side
-        self.proto = proto
-
 class Manager(Node):
     def __init__(self, loc, managerName):
         Node.__init__(self, loc)
         self.name = managerName
 
 class ManagesStmt(Node):
     def __init__(self, loc, managedName):
         Node.__init__(self, loc)
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -4,17 +4,17 @@
 
 import os, re, sys
 from copy import deepcopy
 from collections import OrderedDict
 
 import ipdl.ast
 import ipdl.builtin
 from ipdl.cxx.ast import *
-from ipdl.type import ActorType, ProcessGraph, TypeVisitor, builtinHeaderIncludes
+from ipdl.type import ActorType, TypeVisitor, builtinHeaderIncludes
 
 ##-----------------------------------------------------------------------------
 ## "Public" interface to lowering
 ##
 class LowerToCxx:
     def lower(self, tu):
         '''returns |[ header: File ], [ cpp : File ]| representing the
 lowered form of |tu|'''
@@ -358,21 +358,16 @@ def _callClearManagedActors(managees):
 def _callHasManagedActor(managees, actor):
     return ExprCall(ExprSelect(managees, '.', 'Contains'), args=[ actor ])
 
 def _otherSide(side):
     if side == 'child':  return 'parent'
     if side == 'parent':  return 'child'
     assert 0
 
-def _sideToTransportMode(side):
-    if side == 'parent':  mode = 'SERVER'
-    elif side == 'child': mode = 'CLIENT'
-    return ExprVar('mozilla::ipc::Transport::MODE_'+ mode)
-
 def _ifLogging(topLevelProtocol, stmts):
     iflogging = StmtIf(ExprCall(ExprVar('mozilla::ipc::LoggingEnabledFor'),
                                 args=[ topLevelProtocol ]))
     iflogging.addifstmts(stmts)
     return iflogging
 
 # XXX we need to remove these and install proper error handling
 def _printErrorMessage(msg):
@@ -1471,61 +1466,27 @@ class _GenerateProtocolCode(ipdl.ast.Vis
 
         # Forward declare our own actors.
         self.hdrfile.addthings([
             Whitespace.NL,
             _makeForwardDeclForActor(p.decl.type, 'Parent'),
             _makeForwardDeclForActor(p.decl.type, 'Child')
         ])
 
-        bridges = ProcessGraph.bridgesOf(p.decl.type)
-        for bridge in bridges:
-            ppt, pside = bridge.parent.ptype, _otherSide(bridge.parent.side)
-            cpt, cside = bridge.child.ptype, _otherSide(bridge.child.side)
-            self.hdrfile.addthings([
-                Whitespace.NL,
-                _makeForwardDeclForActor(ppt, pside),
-                _makeForwardDeclForActor(cpt, cside)
-            ])
-            self.cppIncludeHeaders.append(_protocolHeaderName(ppt._ast, pside))
-            self.cppIncludeHeaders.append(_protocolHeaderName(cpt._ast, cside))
-
-        opens = ProcessGraph.opensOf(p.decl.type)
-        for o in opens:
-            optype, oside = o.opener.ptype, o.opener.side
-            self.hdrfile.addthings([
-                Whitespace.NL,
-                _makeForwardDeclForActor(optype, oside)
-            ])
-            self.cppIncludeHeaders.append(_protocolHeaderName(optype._ast, oside))
-
         self.hdrfile.addthing(Whitespace("""
 //-----------------------------------------------------------------------------
 // Code common to %sChild and %sParent
 //
 """% (p.name, p.name)))
 
         # construct the namespace into which we'll stick all our decls
         ns = Namespace(self.protocol.name)
         self.hdrfile.addthing(_putInNamespaces(ns, p.namespaces))
         ns.addstmt(Whitespace.NL)
 
-        # user-facing methods for connecting two process with a new channel
-        for bridge in bridges:
-            bdecl, bdefn = _splitFuncDeclDefn(self.genBridgeFunc(bridge))
-            ns.addstmts([ bdecl, Whitespace.NL ])
-            self.funcDefns.append(bdefn)
-
-        # user-facing methods for opening a new channel across two
-        # existing endpoints
-        for o in opens:
-            odecl, odefn = _splitFuncDeclDefn(self.genOpenFunc(o))
-            ns.addstmts([ odecl, Whitespace.NL ])
-            self.funcDefns.append(odefn)
-
         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'
@@ -1569,65 +1530,16 @@ class _GenerateProtocolCode(ipdl.ast.Vis
                 self.funcDefns.append(rfDefn)
 
             decls.append(Whitespace.NL)
             ns.addstmts(decls)
 
         ns.addstmts([ Whitespace.NL, Whitespace.NL ])
 
 
-    def genBridgeFunc(self, bridge):
-        p = self.protocol
-        parentHandleType = _cxxBareType(ActorType(bridge.parent.ptype),
-                                        _otherSide(bridge.parent.side),
-                                        fq=1)
-        parentvar = ExprVar('parentHandle')
-
-        childHandleType = _cxxBareType(ActorType(bridge.child.ptype),
-                                       _otherSide(bridge.child.side),
-                                       fq=1)
-        childvar = ExprVar('childHandle')
-
-        bridgefunc = MethodDefn(MethodDecl(
-            'Bridge',
-            params=[ Decl(parentHandleType, parentvar.name),
-                     Decl(childHandleType, childvar.name) ],
-            ret=Type.NSRESULT))
-        bridgefunc.addstmt(StmtReturn(ExprCall(
-            ExprVar('mozilla::ipc::Bridge'),
-            args=[ _backstagePass(),
-                   p.callGetChannel(parentvar), p.callOtherPid(parentvar),
-                   p.callGetChannel(childvar), p.callOtherPid(childvar),
-                   _protocolId(p.decl.type),
-                   ExprVar(_messageStartName(p.decl.type) + 'Child')
-                   ])))
-        return bridgefunc
-
-
-    def genOpenFunc(self, o):
-        p = self.protocol
-        localside = o.opener.side
-        openertype = _cxxBareType(ActorType(o.opener.ptype), o.opener.side,
-                                  fq=1)
-        openervar = ExprVar('opener')
-        openfunc = MethodDefn(MethodDecl(
-            'Open',
-            params=[ Decl(openertype, openervar.name) ],
-            ret=Type.BOOL))
-        openfunc.addstmt(StmtReturn(ExprCall(
-            ExprVar('mozilla::ipc::Open'),
-            args=[ _backstagePass(),
-                   p.callGetChannel(openervar), p.callOtherPid(openervar),
-                   _sideToTransportMode(localside),
-                   _protocolId(p.decl.type),
-                   ExprVar(_messageStartName(p.decl.type) + 'Child')
-                   ])))
-        return openfunc
-
-
     # Generate code for PFoo::CreateEndpoints.
     def genEndpointFunc(self):
         p = self.protocol.decl.type
         tparent = _cxxBareType(ActorType(p), 'Parent', fq=1)
         tchild = _cxxBareType(ActorType(p), 'Child', fq=1)
         methodvar = ExprVar('CreateEndpoints')
         rettype = Type.NSRESULT
         parentpidvar = ExprVar('aParentDestPid')
@@ -2605,20 +2517,16 @@ class _GenerateProtocolActorCode(ipdl.as
                     Whitespace.NL
                     ])
 
         self.cls = Class(
             self.clsname,
             inherits=inherits,
             abstract=True)
 
-        bridgeActorsCreated = ProcessGraph.bridgeEndpointsOf(ptype, self.side)
-        opensActorsCreated = ProcessGraph.opensEndpointsOf(ptype, self.side)
-        channelOpenedActors = OrderedDict.fromkeys(bridgeActorsCreated + opensActorsCreated, None)
-
         friends = _FindFriends().findFriends(ptype)
         if ptype.isManaged():
             friends.update(ptype.managers)
 
         # |friend| managed actors so that they can call our Dealloc*()
         friends.update(ptype.manages)
 
         # don't friend ourself if we're a self-managed protocol
@@ -2629,23 +2537,16 @@ class _GenerateProtocolActorCode(ipdl.as
                 _makeForwardDeclForActor(friend, self.prettyside),
                 Whitespace.NL
             ])
             self.cls.addstmts([
                 FriendClassDecl(_actorName(friend.fullname(),
                                            self.prettyside)),
                 Whitespace.NL ])
 
-        for actor in channelOpenedActors:
-            self.hdrfile.addthings([
-                Whitespace.NL,
-                _makeForwardDeclForActor(actor.ptype, actor.side),
-                Whitespace.NL
-            ])
-
         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)
 
@@ -2687,27 +2588,16 @@ class _GenerateProtocolActorCode(ipdl.as
                 virtual=1, pure=1)))
 
             self.cls.addstmt(StmtDecl(MethodDecl(
                 _deallocMethod(managed, self.side).name,
                 params=[ Decl(actortype, 'aActor') ],
                 ret=Type.BOOL,
                 virtual=1, pure=1)))
 
-        for actor in channelOpenedActors:
-            # add the Alloc interface for actors created when a
-            # new channel is opened
-            actortype = _cxxBareType(actor.asType(), actor.side)
-            self.cls.addstmt(StmtDecl(MethodDecl(
-                _allocMethod(actor.ptype, actor.side).name,
-                params=[ Decl(Type('Transport', ptr=1), 'aTransport'),
-                         Decl(Type('ProcessId'), 'aOtherPid') ],
-                ret=actortype,
-                virtual=1, pure=1)))
-
         # ActorDestroy() method; default is no-op
         self.cls.addstmts([
             Whitespace.NL,
             MethodDefn(MethodDecl(
                 _destroyMethod().name,
                 params=[ Decl(_DestroyReason.Type(), 'aWhy') ],
                 ret=Type.VOID,
                 virtual=1, pure=(self.side == 'parent'))),
@@ -2860,21 +2750,16 @@ class _GenerateProtocolActorCode(ipdl.as
             if toplevel.isInterrupt():
                 self.interruptSwitch = StmtSwitch(msgtype)
 
         # implement Send*() methods and add dispatcher cases to
         # message switch()es
         for md in p.messageDecls:
             self.visitMessageDecl(md)
 
-        # Handlers for the creation of actors when a new channel is
-        # opened
-        if len(channelOpenedActors):
-            self.makeChannelOpenedHandlers(channelOpenedActors)
-
         # add default cases
         default = StmtBlock()
         default.addstmt(StmtReturn(_Result.NotKnown))
         self.asyncSwitch.addcase(DefaultLabel(), default)
         if toplevel.isSync() or toplevel.isInterrupt():
             self.syncSwitch.addcase(DefaultLabel(), default)
             if toplevel.isInterrupt():
                 self.interruptSwitch.addcase(DefaultLabel(), default)
@@ -3294,94 +3179,16 @@ class _GenerateProtocolActorCode(ipdl.as
             ifstmt,
             StmtReturn(_Result.Processed)
         ])
         ifstmt.addifstmt(StmtReturn(_Result.PayloadError))
 
         return case
 
 
-    def makeChannelOpenedHandlers(self, actors):
-        handlers = StmtBlock()
-
-        # unpack the transport descriptor et al.
-        msgvar = self.msgvar
-        tdvar = ExprVar('td')
-        pidvar = ExprVar('pid')
-        pvar = ExprVar('protocolid')
-        iffail = StmtIf(ExprNot(ExprCall(
-            ExprVar('mozilla::ipc::UnpackChannelOpened'),
-            args=[ _backstagePass(),
-                   msgvar,
-                   ExprAddrOf(tdvar), ExprAddrOf(pidvar), ExprAddrOf(pvar) ])))
-        iffail.addifstmt(StmtReturn(_Result.PayloadError))
-        handlers.addstmts([
-            StmtDecl(Decl(Type('TransportDescriptor'), tdvar.name)),
-            StmtDecl(Decl(Type('ProcessId'), pidvar.name)),
-            StmtDecl(Decl(Type('ProtocolId'), pvar.name)),
-            iffail,
-            Whitespace.NL
-        ])
-
-        def makeHandlerCase(actor):
-            self.protocolCxxIncludes.append(_protocolHeaderName(actor.ptype._ast,
-                                                                actor.side))
-
-            case = StmtBlock()
-            modevar = _sideToTransportMode(actor.side)
-            tvar = ExprVar('t')
-            iffailopen = StmtIf(ExprNot(ExprAssn(
-                tvar,
-                ExprCall(ExprVar('mozilla::ipc::OpenDescriptor'),
-                         args=[ tdvar, modevar ]))))
-            iffailopen.addifstmt(StmtReturn(_Result.ValuError))
-
-            pvar = ExprVar('p')
-            iffailalloc = StmtIf(ExprNot(ExprAssn(
-                pvar,
-                ExprCall(
-                    _allocMethod(actor.ptype, actor.side),
-                    args=[ _uniqueptrGet(tvar), pidvar ]))))
-            iffailalloc.addifstmt(StmtReturn(_Result.ProcessingError))
-
-            settrans = StmtExpr(ExprCall(
-                ExprSelect(pvar, '->', 'IToplevelProtocol::SetTransport'),
-                args=[ExprMove(tvar)]))
-
-            case.addstmts([
-                StmtDecl(Decl(_uniqueptr(Type('Transport')), tvar.name)),
-                StmtDecl(Decl(Type(_actorName(actor.ptype.name(), actor.side),
-                                   ptr=1), pvar.name)),
-                iffailopen,
-                iffailalloc,
-                settrans,
-                StmtBreak()
-            ])
-            label = _messageStartName(actor.ptype)
-            if actor.side == 'child':
-                label += 'Child'
-            return CaseLabel(label), case
-
-        pswitch = StmtSwitch(pvar)
-        for actor in actors:
-            label, case = makeHandlerCase(actor)
-            pswitch.addcase(label, case)
-
-        die = Block()
-        die.addstmts([ _fatalError('Invalid protocol'),
-                       StmtReturn(_Result.ValuError) ])
-        pswitch.addcase(DefaultLabel(), die)
-
-        handlers.addstmts([
-            pswitch,
-            StmtReturn(_Result.Processed)
-        ])
-        self.asyncSwitch.addcase(CaseLabel('CHANNEL_OPENED_MESSAGE_TYPE'),
-                                 handlers)
-
     ##-------------------------------------------------------------------------
     ## The next few functions are the crux of the IPDL code generator.
     ## They generate code for all the nasty work of message
     ## serialization/deserialization and dispatching handlers for
     ## received messages.
     ##
     def implementPickling(self):
         # pickling of "normal", non-IPDL types
--- a/ipc/ipdl/ipdl/parser.py
+++ b/ipc/ipdl/ipdl/parser.py
@@ -100,41 +100,37 @@ class Parser:
 
 def locFromTok(p, num):
     return Loc(Parser.current.filename, p.lineno(num))
 
 
 ##-----------------------------------------------------------------------------
 
 reserved = set((
-        'as',
         'async',
         'both',
-        'bridges',
         'child',
         'class',
         'compress',
         'compressall',
         '__delete__',
         'delete',                       # reserve 'delete' to prevent its use
         'from',
         'include',
         'intr',
         'manager',
         'manages',
         'namespace',
         'nested',
         'nullable',
-        'opens',
         'or',
         'parent',
         'prio',
         'protocol',
         'returns',
-        'spawns',
         'struct',
         'sync',
         'union',
         'upto',
         'using',
         'verify'))
 tokens = [
     'COLONCOLON', 'ID', 'STRING',
@@ -345,71 +341,19 @@ def p_ProtocolDefn(p):
     protocol.sendSemantics = p[1][1]
     p[0] = protocol
 
     if Parser.current.type == 'header':
         _error(protocol.loc, 'can\'t define a protocol in a header.  Do it in a protocol spec instead.')
 
 
 def p_ProtocolBody(p):
-    """ProtocolBody : SpawnsStmtsOpt"""
+    """ProtocolBody : ManagersStmtOpt"""
     p[0] = p[1]
 
-##--------------------
-## spawns/bridges/opens stmts
-
-def p_SpawnsStmtsOpt(p):
-    """SpawnsStmtsOpt : SpawnsStmt SpawnsStmtsOpt
-                      | BridgesStmtsOpt"""
-    if 2 == len(p):
-        p[0] = p[1]
-    else:
-        p[2].spawnsStmts.insert(0, p[1])
-        p[0] = p[2]
-
-def p_SpawnsStmt(p):
-    """SpawnsStmt : PARENT SPAWNS ID AsOpt ';'
-                  | CHILD SPAWNS ID AsOpt ';'"""
-    p[0] = SpawnsStmt(locFromTok(p, 1), p[1], p[3], p[4])
-
-def p_AsOpt(p):
-    """AsOpt : AS PARENT
-             | AS CHILD
-             | """
-    if 3 == len(p):
-        p[0] = p[2]
-    else:
-        p[0] = 'child'
-
-def p_BridgesStmtsOpt(p):
-    """BridgesStmtsOpt : BridgesStmt BridgesStmtsOpt
-                       | OpensStmtsOpt"""
-    if 2 == len(p):
-        p[0] = p[1]
-    else:
-        p[2].bridgesStmts.insert(0, p[1])
-        p[0] = p[2]
-
-def p_BridgesStmt(p):
-    """BridgesStmt : BRIDGES ID ',' ID ';'"""
-    p[0] = BridgesStmt(locFromTok(p, 1), p[2], p[4])
-
-def p_OpensStmtsOpt(p):
-    """OpensStmtsOpt : OpensStmt OpensStmtsOpt
-                     | ManagersStmtOpt"""
-    if 2 == len(p):
-        p[0] = p[1]
-    else:
-        p[2].opensStmts.insert(0, p[1])
-        p[0] = p[2]
-
-def p_OpensStmt(p):
-    """OpensStmt : PARENT OPENS ID ';'
-                 | CHILD OPENS ID ';'"""
-    p[0] = OpensStmt(locFromTok(p, 1), p[1], p[3])
 
 ##--------------------
 ## manager/manages stmts
 
 def p_ManagersStmtOpt(p):
     """ManagersStmtOpt : ManagersStmt ManagesStmtsOpt
                        | ManagesStmtsOpt"""
     if 2 == len(p):
--- a/ipc/ipdl/ipdl/type.py
+++ b/ipc/ipdl/ipdl/type.py
@@ -10,27 +10,16 @@ from ipdl.ast import TypeSpec, UnionDecl
 from ipdl.ast import ASYNC, SYNC, INTR
 from ipdl.ast import IN, OUT, INOUT
 from ipdl.ast import NOT_NESTED, INSIDE_SYNC_NESTED, INSIDE_CPOW_NESTED
 import ipdl.builtin as builtin
 
 _DELETE_MSG = '__delete__'
 
 
-def _otherside(side):
-    if side == 'parent':  return 'child'
-    elif side == 'child': return 'parent'
-    else:  assert 0 and 'unknown side "%s"'% (side)
-
-def cartesian_product(s1, s2):
-    for e1 in s1:
-        for e2 in s2:
-            yield (e1, e2)
-
-
 class TypeVisitor:
     def __init__(self):
         self.visited = set()
 
     def defaultVisit(self, node, *args):
         raise Exception, "INTERNAL ERROR: no visitor for node type `%s'"% (
             node.__class__.__name__)
 
@@ -218,59 +207,36 @@ class MessageType(IPDLType):
 
     def isIn(self): return self.direction is IN
     def isOut(self): return self.direction is OUT
     def isInout(self): return self.direction is INOUT
 
     def hasImplicitActorParam(self):
         return self.isCtor() or self.isDtor()
 
-class Bridge:
-    def __init__(self, parentPtype, childPtype):
-        assert parentPtype.isToplevel() and childPtype.isToplevel()
-        self.parent = parentPtype
-        self.child = childPtype
-
-    def __cmp__(self, o):
-        return cmp(self.parent, o.parent) or cmp(self.child, o.child)
-    def __eq__(self, o):
-        return self.parent == o.parent and self.child == o.child
-    def __hash__(self):
-        return hash(self.parent) + hash(self.child)
-
 class ProtocolType(IPDLType):
     def __init__(self, qname, nestedRange, sendSemantics):
         self.qname = qname
         self.nestedRange = nestedRange
         self.sendSemantics = sendSemantics
-        self.spawns = set()             # ProtocolType
-        self.opens = set()              # ProtocolType
         self.managers = []           # ProtocolType
         self.manages = [ ]
         self.hasDelete = False
         self.hasReentrantDelete = False
     def isProtocol(self): return True
 
     def name(self):
         return self.qname.baseid
     def fullname(self):
         return str(self.qname)
 
     def addManager(self, mgrtype):
         assert mgrtype.isIPDL() and mgrtype.isProtocol()
         self.managers.append(mgrtype)
 
-    def addSpawn(self, ptype):
-        assert self.isToplevel() and  ptype.isToplevel()
-        self.spawns.add(ptype)
-
-    def addOpen(self, ptype):
-        assert self.isToplevel() and  ptype.isToplevel()
-        self.opens.add(ptype)
-
     def managedBy(self, mgr):
         self.managers = list(mgr)
 
     def toplevel(self):
         if self.isToplevel():
             return self
         for mgr in self.managers:
             if mgr is not self:
@@ -551,20 +517,16 @@ With this information, it finally type c
         # and location of declaration
         if not runpass(GatherDecls(builtinUsing, self.errors)):
             return False
 
         # now that the nodes have decls, type checking is much easier.
         if not runpass(CheckTypes(self.errors)):
             return False
 
-        if not (runpass(BuildProcessGraph(self.errors))
-                and runpass(CheckProcessGraph(self.errors))):
-            return False
-
         return True
 
     def reportErrors(self, errout):
         for error in self.errors:
             print >>errout, error
 
 
 class TcheckVisitor(Visitor):
@@ -784,25 +746,16 @@ class GatherDecls(TcheckVisitor):
             type=ipdltype,
             shortname=using.type.basename(),
             fullname=fullname)
 
     def visitProtocol(self, p):
         # protocol scope
         self.symtab.enterScope(p)
 
-        for spawns in p.spawnsStmts:
-            spawns.accept(self)
-
-        for bridges in p.bridgesStmts:
-            bridges.accept(self)
-
-        for opens in p.opensStmts:
-            opens.accept(self)
-
         seenmgrs = set()
         for mgr in p.managers:
             if mgr.name in seenmgrs:
                 self.error(mgr.loc, "manager `%s' appears multiple times",
                            mgr.name)
                 continue
 
             seenmgrs.add(mgr.name)
@@ -846,43 +799,16 @@ class GatherDecls(TcheckVisitor):
         # be generated.  they're not relevant to IPDL itself, but
         # those ("invisible") symbols can clash with others in the
         # IPDL spec, and we'd like to catch those before C++ compilers
         # are allowed to obfuscate the error
 
         self.symtab.exitScope(p)
 
 
-    def visitSpawnsStmt(self, spawns):
-        pname = spawns.proto
-        spawns.proto = self.symtab.lookup(pname)
-        if spawns.proto is None:
-            self.error(spawns.loc,
-                       "spawned protocol `%s' has not been declared",
-                       pname)
-
-    def visitBridgesStmt(self, bridges):
-        def lookup(p):
-            decl = self.symtab.lookup(p)
-            if decl is None:
-                self.error(bridges.loc,
-                           "bridged protocol `%s' has not been declared", p)
-            return decl
-        bridges.parentSide = lookup(bridges.parentSide)
-        bridges.childSide = lookup(bridges.childSide)
-
-    def visitOpensStmt(self, opens):
-        pname = opens.proto
-        opens.proto = self.symtab.lookup(pname)
-        if opens.proto is None:
-            self.error(opens.loc,
-                       "opened protocol `%s' has not been declared",
-                       pname)
-
-
     def visitManager(self, mgr):
         mgrdecl = self.symtab.lookup(mgr.name)
         pdecl = mgr.of.decl
         assert pdecl
 
         pname, mgrname = pdecl.shortname, mgr.name
         loc = mgr.loc
 
@@ -1102,31 +1028,16 @@ class CheckTypes(TcheckVisitor):
 
 
     def visitProtocol(self, p):
         self.ptype = p.decl.type
 
         # check that we require no more "power" than our manager protocols
         ptype, pname = p.decl.type, p.decl.shortname
 
-        if len(p.spawnsStmts) and not ptype.isToplevel():
-            self.error(p.decl.loc,
-                       "protocol `%s' is not top-level and so cannot declare |spawns|",
-                       pname)
-
-        if len(p.bridgesStmts) and not ptype.isToplevel():
-            self.error(p.decl.loc,
-                       "protocol `%s' is not top-level and so cannot declare |bridges|",
-                       pname)
-
-        if len(p.opensStmts) and not ptype.isToplevel():
-            self.error(p.decl.loc,
-                       "protocol `%s' is not top-level and so cannot declare |opens|",
-                       pname)
-
         for mgrtype in ptype.managers:
             if mgrtype is not None and ptype.needsMoreJuiceThan(mgrtype):
                 self.error(
                     p.decl.loc,
                     "protocol `%s' requires more powerful send semantics than its manager `%s' provides",
                     pname, mgrtype.name())
 
         # XXX currently we don't require a delete() message of top-level
@@ -1151,67 +1062,16 @@ class CheckTypes(TcheckVisitor):
             self.error(
                 p.decl.loc,
                 "top-level protocol `%s' cannot manage itself",
                 p.name)
 
         return Visitor.visitProtocol(self, p)
 
 
-    def visitSpawnsStmt(self, spawns):
-        if not self.ptype.isToplevel():
-            self.error(spawns.loc,
-                       "only top-level protocols can have |spawns| statements; `%s' cannot",
-                       self.ptype.name())
-            return
-
-        spawnedType = spawns.proto.type
-        if not (spawnedType.isIPDL() and spawnedType.isProtocol()
-                and spawnedType.isToplevel()):
-            self.error(spawns.loc,
-                       "cannot spawn non-top-level-protocol `%s'",
-                       spawnedType.name())
-        else:
-            self.ptype.addSpawn(spawnedType)
-
-
-    def visitBridgesStmt(self, bridges):
-        if not self.ptype.isToplevel():
-            self.error(bridges.loc,
-                       "only top-level protocols can have |bridges| statements; `%s' cannot",
-                       self.ptype.name())
-            return
-
-        parentType = bridges.parentSide.type
-        childType = bridges.childSide.type
-        if not (parentType.isIPDL() and parentType.isProtocol()
-                and childType.isIPDL() and childType.isProtocol()
-                and parentType.isToplevel() and childType.isToplevel()):
-            self.error(bridges.loc,
-                       "cannot bridge non-top-level-protocol(s) `%s' and `%s'",
-                       parentType.name(), childType.name())
-
-
-    def visitOpensStmt(self, opens):
-        if not self.ptype.isToplevel():
-            self.error(opens.loc,
-                       "only top-level protocols can have |opens| statements; `%s' cannot",
-                       self.ptype.name())
-            return
-
-        openedType = opens.proto.type
-        if not (openedType.isIPDL() and openedType.isProtocol()
-                and openedType.isToplevel()):
-            self.error(opens.loc,
-                       "cannot open non-top-level-protocol `%s'",
-                       openedType.name())
-        else:
-            self.ptype.addOpen(openedType)
-
-
     def visitManagesStmt(self, mgs):
         pdecl = mgs.manager.decl
         ptype, pname = pdecl.type, pdecl.shortname
 
         mgsdecl = mgs.decl
         mgstype, mgsname = mgsdecl.type, mgsdecl.shortname
 
         loc = mgs.loc
@@ -1293,335 +1153,8 @@ class CheckTypes(TcheckVisitor):
                 "message `%s' in protocol `%s' requests compression but is not async or is special (ctor or dtor)",
                 mname[:-len('constructor')], pname)
 
         if mtype.isCtor() and not ptype.isManagerOf(mtype.constructedType()):
             self.error(
                 loc,
                 "ctor for protocol `%s', which is not managed by protocol `%s'",
                 mname[:-len('constructor')], pname)
-
-
-##-----------------------------------------------------------------------------
-
-class Process:
-    def __init__(self):
-        self.actors = set()         # set(Actor)
-        self.edges = { }            # Actor -> [ SpawnsEdge ]
-        self.spawn = set()          # set(Actor)
-
-    def edge(self, spawner, spawn):
-        if spawner not in self.edges:  self.edges[spawner] = [ ]
-        self.edges[spawner].append(SpawnsEdge(spawner, spawn))
-        self.spawn.add(spawn)
-
-    def iteredges(self):
-        for edgelist in self.edges.itervalues():
-            for edge in edgelist:
-                yield edge
-
-    def merge(self, o):
-        'Merge the Process |o| into this Process'
-        if self == o:
-            return
-        for actor in o.actors:
-            ProcessGraph.actorToProcess[actor] = self
-        self.actors.update(o.actors)
-        self.edges.update(o.edges)
-        self.spawn.update(o.spawn)
-        ProcessGraph.processes.remove(o)
-
-    def spawns(self, actor):
-        return actor in self.spawn
-
-    def __cmp__(self, o):  return cmp(self.actors, o.actors)
-    def __eq__(self, o):   return self.actors == o.actors
-    def __hash__(self):    return hash(id(self))
-    def __repr__(self):
-        return reduce(lambda a, x: str(a) + str(x) +'|', self.actors, '|')
-    def __str__(self):     return repr(self)
-
-class Actor:
-    def __init__(self, ptype, side):
-        self.ptype = ptype
-        self.side = side
-
-    def asType(self):
-        return ActorType(self.ptype)
-    def other(self):
-        return Actor(self.ptype, _otherside(self.side))
-
-    def __cmp__(self, o):
-        return cmp(self.ptype, o.ptype) or cmp(self.side, o.side)
-    def __eq__(self, o):
-        return self.ptype == o.ptype and self.side == o.side
-    def __hash__(self):  return hash(repr(self))
-    def __repr__(self):  return '%s%s'% (self.ptype.name(), self.side.title())
-    def __str__(self):   return repr(self)
-
-class SpawnsEdge:
-    def __init__(self, spawner, spawn):
-        self.spawner = spawner      # Actor
-        self.spawn = spawn          # Actor
-    def __repr__(self):
-        return '(%r)--spawns-->(%r)'% (self.spawner, self.spawn)
-    def __str__(self):  return repr(self)
-
-class BridgeEdge:
-    def __init__(self, bridgeProto, parent, child):
-        self.bridgeProto = bridgeProto # ProtocolType
-        self.parent = parent           # Actor
-        self.child = child             # Actor
-    def __repr__(self):
-        return '(%r)--%s bridge-->(%r)'% (
-            self.parent, self.bridgeProto.name(), self.child)
-    def __str__(self):  return repr(self)
-
-class OpensEdge:
-    def __init__(self, opener, openedProto):
-        self.opener = opener            # Actor
-        self.openedProto = openedProto  # ProtocolType
-    def __repr__(self):
-        return '(%r)--opens-->(%s)'% (self.opener, self.openedProto.name())
-    def __str__(self):  return repr(self)
-
-# "singleton" class with state that persists across type checking of
-# all protocols
-class ProcessGraph:
-    processes = set()                   # set(Process)
-    bridges = { }                       # ProtocolType -> [ BridgeEdge ]
-    opens = { }                         # ProtocolType -> [ OpensEdge ]
-    actorToProcess = { }                # Actor -> Process
-    visitedSpawns = set()               # set(ActorType)
-    visitedBridges = set()              # set(ActorType)
-
-    @classmethod
-    def findProcess(cls, actor):
-        return cls.actorToProcess.get(actor, None)
-
-    @classmethod
-    def getProcess(cls, actor):
-        if actor not in cls.actorToProcess:
-            p = Process()
-            p.actors.add(actor)
-            cls.processes.add(p)
-            cls.actorToProcess[actor] = p
-        return cls.actorToProcess[actor]
-
-    @classmethod
-    def bridgesOf(cls, bridgeP):
-        return cls.bridges.get(bridgeP, [])
-
-    @classmethod
-    def bridgeEndpointsOf(cls, ptype, side):
-        actor = Actor(ptype, side)
-        endpoints = []
-        for b in cls.iterbridges():
-            if b.parent == actor:
-                endpoints.append(Actor(b.bridgeProto, 'parent'))
-            if b.child == actor:
-                endpoints.append(Actor(b.bridgeProto, 'child'))
-        return endpoints
-
-    @classmethod
-    def iterbridges(cls):
-        for edges in cls.bridges.itervalues():
-            for bridge in edges:
-                yield bridge
-
-    @classmethod
-    def opensOf(cls, openedP):
-        return cls.opens.get(openedP, [])
-
-    @classmethod
-    def opensEndpointsOf(cls, ptype, side):
-        actor = Actor(ptype, side)
-        endpoints = []
-        for o in cls.iteropens():
-            if actor == o.opener:
-                endpoints.append(Actor(o.openedProto, o.opener.side))
-            elif actor == o.opener.other():
-                endpoints.append(Actor(o.openedProto, o.opener.other().side))
-        return endpoints
-
-    @classmethod
-    def iteropens(cls):
-        for edges in cls.opens.itervalues():
-            for opens in edges:
-                yield opens
-
-    @classmethod
-    def spawn(cls, spawner, remoteSpawn):
-        localSpawn = remoteSpawn.other()
-        spawnerProcess = ProcessGraph.getProcess(spawner)
-        spawnerProcess.merge(ProcessGraph.getProcess(localSpawn))
-        spawnerProcess.edge(spawner, remoteSpawn)
-
-    @classmethod
-    def bridge(cls, parent, child, bridgeP):
-        bridgeParent = Actor(bridgeP, 'parent')
-        parentProcess = ProcessGraph.getProcess(parent)
-        parentProcess.merge(ProcessGraph.getProcess(bridgeParent))
-        bridgeChild = Actor(bridgeP, 'child')
-        childProcess = ProcessGraph.getProcess(child)
-        childProcess.merge(ProcessGraph.getProcess(bridgeChild))
-        if bridgeP not in cls.bridges:
-            cls.bridges[bridgeP] = [ ]
-        cls.bridges[bridgeP].append(BridgeEdge(bridgeP, parent, child))
-
-    @classmethod
-    def open(cls, opener, opened, openedP):
-        remoteOpener, remoteOpened, = opener.other(), opened.other()
-        openerProcess = ProcessGraph.getProcess(opener)
-        openerProcess.merge(ProcessGraph.getProcess(opened))
-        remoteOpenerProcess = ProcessGraph.getProcess(remoteOpener)
-        remoteOpenerProcess.merge(ProcessGraph.getProcess(remoteOpened))
-        if openedP not in cls.opens:
-            cls.opens[openedP] = [ ]
-        cls.opens[openedP].append(OpensEdge(opener, openedP))
-
-
-class BuildProcessGraph(TcheckVisitor):
-    class findSpawns(TcheckVisitor):
-        def __init__(self, errors):
-            TcheckVisitor.__init__(self, None, errors)
-
-        def visitTranslationUnit(self, tu):
-            TcheckVisitor.visitTranslationUnit(self, tu)
-
-        def visitInclude(self, inc):
-            if inc.tu.protocol:
-                inc.tu.protocol.accept(self)
-
-        def visitProtocol(self, p):
-            ptype = p.decl.type
-            # non-top-level protocols don't add any information
-            if not ptype.isToplevel() or ptype in ProcessGraph.visitedSpawns:
-                return
-
-            ProcessGraph.visitedSpawns.add(ptype)
-            self.visiting = ptype
-            ProcessGraph.getProcess(Actor(ptype, 'parent'))
-            ProcessGraph.getProcess(Actor(ptype, 'child'))
-            return TcheckVisitor.visitProtocol(self, p)
-
-        def visitSpawnsStmt(self, spawns):
-            # The picture here is:
-            #  [ spawner | localSpawn | ??? ]  (process 1)
-            #                  |
-            #                  |
-            #            [ remoteSpawn | ???]  (process 2)
-            #
-            # A spawns stmt tells us that |spawner| and |localSpawn|
-            # are in the same process.
-            spawner = Actor(self.visiting, spawns.side)
-            remoteSpawn = Actor(spawns.proto.type, spawns.spawnedAs)
-            ProcessGraph.spawn(spawner, remoteSpawn)
-
-    def __init__(self, errors):
-        TcheckVisitor.__init__(self, None, errors)
-        self.visiting = None            # ActorType
-        self.visited = set()            # set(ActorType)
-
-    def visitTranslationUnit(self, tu):
-        tu.accept(self.findSpawns(self.errors))
-        TcheckVisitor.visitTranslationUnit(self, tu)
-
-    def visitInclude(self, inc):
-        if inc.tu.protocol:
-            inc.tu.protocol.accept(self)
-
-    def visitProtocol(self, p):
-        ptype = p.decl.type
-        # non-top-level protocols don't add any information
-        if not ptype.isToplevel() or ptype in ProcessGraph.visitedBridges:
-            return
-
-        ProcessGraph.visitedBridges.add(ptype)
-        self.visiting = ptype
-        return TcheckVisitor.visitProtocol(self, p)
-
-    def visitBridgesStmt(self, bridges):
-        bridgeProto = self.visiting
-        parentSideProto = bridges.parentSide.type
-        childSideProto = bridges.childSide.type
-
-        # the picture here is:
-        #                                                   (process 1|
-        #  [ parentSide(Parent|Child) | childSide(Parent|Child) | ... ]
-        #         |                                       |
-        #         |                        (process 2|    |
-        #  [ parentSide(Child|Parent) | bridgeParent ]    |
-        #                                   |             |
-        #                                   |             |       (process 3|
-        #                           [ bridgeChild | childSide(Child|Parent) ]
-        #
-        # First we have to figure out which parentSide/childSide
-        # actors live in the same process.  The possibilities are {
-        # parent, child } x { parent, child }.  (Multiple matches
-        # aren't allowed yet.)  Then we make ProcessGraph aware of the
-        # new bridge.
-        parentSideActor, childSideActor = None, None
-        pc = ( 'parent', 'child' )
-        for parentSide, childSide in cartesian_product(pc, pc):
-            pactor = Actor(parentSideProto, parentSide)
-            pproc = ProcessGraph.findProcess(pactor)
-            cactor = Actor(childSideProto, childSide)
-            cproc = ProcessGraph.findProcess(cactor)
-            assert pproc and cproc
-
-            if pproc == cproc:
-                if parentSideActor is not None:
-                    if parentSideProto != childSideProto:
-                        self.error(bridges.loc,
-                                   "ambiguous bridge `%s' between `%s' and `%s'",
-                                   bridgeProto.name(),
-                                   parentSideProto.name(),
-                                   childSideProto.name())
-                else:
-                    parentSideActor, childSideActor = pactor.other(), cactor.other()
-
-        if parentSideActor is None:
-            self.error(bridges.loc,
-                       "`%s' and `%s' cannot be bridged by `%s' ",
-                       parentSideProto.name(), childSideProto.name(),
-                       bridgeProto.name())
-
-        ProcessGraph.bridge(parentSideActor, childSideActor, bridgeProto)
-
-    def visitOpensStmt(self, opens):
-        openedP = opens.proto.type
-        opener = Actor(self.visiting, opens.side)
-        opened = Actor(openedP, opens.side)
-
-        # The picture here is:
-        #  [ opener       | opened ]   (process 1)
-        #      |               |
-        #      |               |
-        #  [ remoteOpener | remoteOpened ]  (process 2)
-        #
-        # An opens stmt tells us that the pairs |opener|/|opened|
-        # and |remoteOpener|/|remoteOpened| are each in the same
-        # process.
-        ProcessGraph.open(opener, opened, openedP)
-
-
-class CheckProcessGraph(TcheckVisitor):
-    def __init__(self, errors):
-        TcheckVisitor.__init__(self, None, errors)
-
-    # TODO: verify spawns-per-process assumption and check that graph
-    # is a dag
-    def visitTranslationUnit(self, tu):
-        if 0:
-            print 'Processes'
-            for process in ProcessGraph.processes:
-                print '  ', process
-                for edge in process.iteredges():
-                    print '    ', edge
-            print 'Bridges'
-            for bridgeList in ProcessGraph.bridges.itervalues():
-                for bridge in bridgeList:
-                    print '  ', bridge
-            print 'Opens'
-            for opensList in ProcessGraph.opens.itervalues():
-                for opens in opensList:
-                    print '  ', opens