Bug 1309799 - Generate StringFromIPCMessageType and use it in MessageChannel::MaybeHandleError. r?billm draft
authorKan-Ru Chen <kanru@kanru.info>
Thu, 13 Oct 2016 14:18:45 +0800
changeset 428293 1cc46c4c47e91d6993a7ed201e77f1c19645b1a2
parent 424520 22be4ae74653b25186665f22e52a50e7027fd36b
child 428294 93c44cec1208bbad8e1b9090607ebbf53da8de52
push id33277
push userbmo:kchen@mozilla.com
push dateSat, 22 Oct 2016 03:41:26 +0000
reviewersbillm
bugs1309799
milestone52.0a1
Bug 1309799 - Generate StringFromIPCMessageType and use it in MessageChannel::MaybeHandleError. r?billm MozReview-Commit-ID: HSuAAM0JdjS
ipc/glue/MessageChannel.cpp
ipc/glue/ProtocolUtils.cpp
ipc/glue/ProtocolUtils.h
ipc/ipdl/ipdl.py
ipc/ipdl/ipdl/__init__.py
ipc/ipdl/ipdl/lower.py
ipc/ipdl/moz.build
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -2033,17 +2033,17 @@ MessageChannel::MaybeHandleError(Result 
 
     default:
         NS_RUNTIMEABORT("unknown Result code");
         return false;
     }
 
     char reason[512];
     SprintfLiteral(reason,"(msgtype=0x%X,name=%s) %s",
-                   aMsg.type(), aMsg.name(), errorMsg);
+                   aMsg.type(), StringFromIPCMessageType(aMsg.type()), errorMsg);
 
     PrintErrorMessage(mSide, channelName, reason);
 
     mListener->OnProcessingError(code, reason);
 
     return false;
 }
 
--- a/ipc/glue/ProtocolUtils.cpp
+++ b/ipc/glue/ProtocolUtils.cpp
@@ -259,25 +259,25 @@ AnnotateCrashReportWithErrno(const char*
     nsCString(tag),
     nsPrintfCString("%d", error));
 }
 #endif
 
 void
 LogMessageForProtocol(const char* aTopLevelProtocol, base::ProcessId aOtherPid,
                       const char* aContextDescription,
-                      const char* aMessageDescription,
+                      uint32_t aMessageId,
                       MessageDirection aDirection)
 {
   nsPrintfCString logMessage("[time: %" PRId64 "][%d%s%d] [%s] %s %s\n",
                              PR_Now(), base::GetCurrentProcId(),
                              aDirection == MessageDirection::eReceiving ? "<-" : "->",
                              aOtherPid, aTopLevelProtocol,
                              aContextDescription,
-                             aMessageDescription);
+                             StringFromIPCMessageType(aMessageId));
 #ifdef ANDROID
   __android_log_write(ANDROID_LOG_INFO, "GeckoIPC", logMessage.get());
 #endif
   fputs(logMessage.get(), stderr);
 }
 
 void
 ProtocolErrorBreakpoint(const char* aMsg)
--- a/ipc/glue/ProtocolUtils.h
+++ b/ipc/glue/ProtocolUtils.h
@@ -294,17 +294,17 @@ LoggingEnabledFor(const char *aTopLevelP
 enum class MessageDirection {
     eSending,
     eReceiving,
 };
 
 MOZ_NEVER_INLINE void
 LogMessageForProtocol(const char* aTopLevelProtocol, base::ProcessId aOtherPid,
                       const char* aContextDescription,
-                      const char* aMessageDescription,
+                      uint32_t aMessageId,
                       MessageDirection aDirection);
 
 MOZ_NEVER_INLINE void
 ProtocolErrorBreakpoint(const char* aMsg);
 
 // The code generator calls this function for errors which come from the
 // methods of protocols.  Doing this saves codesize by making the error
 // cases significantly smaller.
@@ -565,16 +565,18 @@ CreateEndpoints(const PrivateIPDLInterfa
 
   return NS_OK;
 }
 
 void
 TableToArray(const nsTHashtable<nsPtrHashKey<void>>& aTable,
              nsTArray<void*>& aArray);
 
+const char* StringFromIPCMessageType(uint32_t aMessageType);
+
 } // namespace ipc
 
 template<typename Protocol>
 class ManagedContainer : public nsTHashtable<nsPtrHashKey<Protocol>>
 {
   typedef nsTHashtable<nsPtrHashKey<Protocol>> BaseClass;
 
 public:
--- a/ipc/ipdl/ipdl.py
+++ b/ipc/ipdl/ipdl.py
@@ -41,16 +41,17 @@ options, files = op.parse_args()
 headersdir = options.headersdir
 cppdir = options.cppdir
 includedirs = [ os.path.abspath(incdir) for incdir in options.includedirs ]
 
 if not len(files):
     op.error("No IPDL files specified")
 
 ipcmessagestartpath = os.path.join(headersdir, 'IPCMessageStart.h')
+ipc_msgtype_name_path = os.path.join(cppdir, 'IPCMessageTypeName.cpp')
 
 # Compiling the IPDL files can take a long time, even on a fast machine.
 # Check to see whether we need to do any work.
 latestipdlmod = max(os.stat(f).st_mtime
                     for f in itertools.chain(files,
                                              iter_modules_in_path(mozpath.dirname(__file__))))
 
 def outputModTime(f):
@@ -99,16 +100,17 @@ def alloutputfiles():
 earliestoutputmod = min(outputModTime(f) for f in alloutputfiles())
 
 if latestipdlmod < earliestoutputmod:
     sys.exit(0)
 
 log(2, 'Generated C++ headers will be generated relative to "%s"', headersdir)
 log(2, 'Generated C++ sources will be generated in "%s"', cppdir)
 
+allmessages = {}
 allprotocols = []
 
 def normalizedFilename(f):
     if f == '-':
         return '<stdin>'
     return f
 
 # First pass: parse and type-check all protocols
@@ -138,21 +140,21 @@ for f in files:
         ipdl.genipdl(ast, codedir)
 
 # Second pass: generate code
 for f in files:
     # Read from parser cache
     filename = normalizedFilename(f)
     ast = ipdl.parse(None, filename, includedirs=includedirs)
     ipdl.gencxx(filename, ast, headersdir, cppdir)
-    
+
     if ast.protocol:
+        allmessages[ast.protocol.name] = ipdl.genmsgenum(ast)
         allprotocols.append('%sMsgStart' % ast.protocol.name)
 
-
 allprotocols.sort()
 
 ipcmsgstart = StringIO()
 
 print >>ipcmsgstart, """
 // CODE GENERATED by ipdl.py. Do not edit.
 
 #ifndef IPCMessageStart_h
@@ -169,9 +171,62 @@ print >>ipcmsgstart, """
   LastMsgIndex
 };
 
 static_assert(LastMsgIndex <= 65536, "need to update IPC_MESSAGE_MACRO");
 
 #endif // ifndef IPCMessageStart_h
 """
 
+ipc_msgtype_name = StringIO()
+print >>ipc_msgtype_name, """
+// CODE GENERATED by ipdl.py. Do not edit.
+#include <cstdint>
+
+#include "IPCMessageStart.h"
+
+using std::uint32_t;
+
+namespace {
+
+enum IPCMessages {
+"""
+
+for protocol in sorted(allmessages.keys()):
+    for (msg, num) in allmessages[protocol].idnums:
+        if num:
+            print >>ipc_msgtype_name, "  %s = %s," % (msg, num)
+        elif not msg.endswith('End'):
+            print >>ipc_msgtype_name,  "  %s__%s," % (protocol, msg)
+
+print >>ipc_msgtype_name, """
+};
+
+} // anonymous namespace
+
+namespace mozilla {
+namespace ipc {
+
+const char* StringFromIPCMessageType(uint32_t aMessageType)
+{
+  switch (aMessageType) {
+"""
+
+for protocol in sorted(allmessages.keys()):
+    for (msg, num) in allmessages[protocol].idnums:
+        if num or msg.endswith('End'):
+            continue
+        print >>ipc_msgtype_name, """
+  case %s__%s:
+    return "%s::%s";""" % (protocol, msg, protocol, msg)
+
+print >>ipc_msgtype_name, """
+  default:
+    return "???";
+  }
+}
+
+} // namespace ipc
+} // namespace mozilla
+"""
+
 ipdl.writeifmodified(ipcmsgstart.getvalue(), ipcmessagestartpath)
+ipdl.writeifmodified(ipc_msgtype_name.getvalue(), ipc_msgtype_name_path)
--- a/ipc/ipdl/ipdl/__init__.py
+++ b/ipc/ipdl/ipdl/__init__.py
@@ -3,17 +3,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 __all__ = [ 'gencxx', 'genipdl', 'parse', 'typecheck', 'writeifmodified' ]
 
 import os, sys
 from cStringIO import StringIO
 
 from ipdl.cgen import IPDLCodeGen
-from ipdl.lower import LowerToCxx
+from ipdl.lower import LowerToCxx, msgenums
 from ipdl.parser import Parser
 from ipdl.type import TypeCheck
 
 from ipdl.cxx.cgen import CxxCodeGen
 
 
 def parse(specstring, filename='/stdin', includedirs=[ ], errout=sys.stderr):
     '''Return an IPDL AST if parsing was successful.  Print errors to |errout|
@@ -54,16 +54,19 @@ def gencxx(ipdlfilename, ast, outheaders
         CxxCodeGen(tempfile).cgen(ast)
         writeifmodified(tempfile.getvalue(), filename)
 
 
 def genipdl(ast, outdir):
     return IPDLCodeGen().cgen(ast)
 
 
+def genmsgenum(ast):
+    return msgenums(ast.protocol, pretty=True)
+
 def writeifmodified(contents, file):
     dir = os.path.dirname(file)
     os.path.exists(dir) or os.makedirs(dir)
 
     oldcontents = None
     if os.path.exists(file):
         fd = open(file, 'rb')
         oldcontents = fd.read()
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -1460,16 +1460,29 @@ with some new IPDL/C++ nodes that are tu
 
     def visitTransitionStmt(self, ts):
         name = ts.state.decl.progname
         ts.state.decl.cxxname = name
         ts.state.decl.cxxenum = ExprVar(self.protocolName +'::'+ name)
 
 ##-----------------------------------------------------------------------------
 
+def msgenums(protocol, pretty=False):
+    msgenum = TypeEnum('MessageType')
+    msgstart = _messageStartName(protocol.decl.type) +' << 16'
+    msgenum.addId(protocol.name + 'Start', msgstart)
+
+    for md in protocol.messageDecls:
+        msgenum.addId(md.prettyMsgName() if pretty else  md.msgId())
+        if md.hasReply():
+            msgenum.addId(md.prettyReplyName() if pretty else md.replyId())
+
+    msgenum.addId(protocol.name +'End')
+    return msgenum
+
 class _GenerateProtocolCode(ipdl.ast.Visitor):
     '''Creates code common to both the parent and child actors.'''
     def __init__(self):
         self.protocol = None     # protocol we're generating a class for
         self.hdrfile = None      # what will become Protocol.h
         self.cppfile = None      # what will become Protocol.cpp
         self.cppIncludeHeaders = []
         self.structUnionDefns = []
@@ -1658,27 +1671,17 @@ class _GenerateProtocolCode(ipdl.ast.Vis
             startstate = p.transitionStmts[0].state.decl.cxxname
         else:
             startstate = _nullState().name
         stateenum.addId(_startState().name, startstate)
 
         ns.addstmts([ StmtDecl(Decl(stateenum,'')), Whitespace.NL ])
 
         # spit out message type enum and classes
-        msgenum = TypeEnum('MessageType')
-        msgstart = _messageStartName(self.protocol.decl.type) +' << 16'
-        msgenum.addId(self.protocol.name + 'Start', msgstart)
-        #msgenum.addId(self.protocol.name +'PreStart', '('+ msgstart +') - 1')
-
-        for md in p.messageDecls:
-            msgenum.addId(md.msgId())
-            if md.hasReply():
-                msgenum.addId(md.replyId())
-
-        msgenum.addId(self.protocol.name +'End')
+        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 = []
@@ -5190,25 +5193,16 @@ class _GenerateProtocolActorCode(ipdl.as
 
 
     def deserializeMessage(self, md, side, errfn):
         msgvar = self.msgvar
         itervar = self.itervar
         msgexpr = ExprAddrOf(msgvar)
         isctor = md.decl.type.isCtor()
         stmts = ([
-            # this is kind of naughty, but the only two other options
-            # are forwarding the message name (yuck) or making the
-            # IPDL|*Channel abstraction leak more
-            StmtExpr(ExprCall(
-                ExprSelect(
-                    ExprCast(msgvar, Type('Message', ref=1), const=1),
-                    '.', 'set_name'),
-                args=[ ExprLiteral.String(md.prettyMsgName(self.protocol.name
-                                                           +'::')) ])),
             self.logMessage(md, msgexpr, 'Received ',
                             receiving=True),
             self.profilerLabel('Recv', md.decl.progname),
             Whitespace.NL
         ])
 
         if 0 == len(md.params):
             return stmts
@@ -5361,17 +5355,17 @@ class _GenerateProtocolActorCode(ipdl.as
         actorname = _actorName(self.protocol.name, self.side)
 
         return _ifLogging(ExprLiteral.String(actorname),
                           [ StmtExpr(ExprCall(
                               ExprVar('mozilla::ipc::LogMessageForProtocol'),
                               args=[ ExprLiteral.String(actorname),
                                      self.protocol.callOtherPid(actor),
                                      ExprLiteral.String(pfx),
-                                     ExprCall(ExprSelect(msgptr, '->', 'name')),
+                                     ExprCall(ExprSelect(msgptr, '->', 'type')),
                                      ExprVar('mozilla::ipc::MessageDirection::eReceiving'
                                              if receiving
                                              else 'mozilla::ipc::MessageDirection::eSending') ])) ])
 
     def profilerLabel(self, tag, msgname):
         return StmtExpr(ExprCall(ExprVar('PROFILER_LABEL'),
                                  [ ExprLiteral.String('IPDL::' + self.protocol.name),
                                    ExprLiteral.String(tag + msgname),
--- a/ipc/ipdl/moz.build
+++ b/ipc/ipdl/moz.build
@@ -4,13 +4,16 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 if CONFIG['MOZ_IPDL_TESTS']:
     DIRS += ['test']
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
+# Generated by ipdl.py
+SOURCES += ['!IPCMessageTypeName.cpp']
+
 FINAL_LIBRARY = 'xul'
 
 # We #include some things in the dom/plugins/ directory that rely on
 # toolkit libraries.
 CXXFLAGS += CONFIG['TK_CFLAGS']