[Python-checkins] CVS: python/dist/src/Tools/compiler/compiler transformer.py,1.22,1.23

Jeremy Hylton jhylton@users.sourceforge.net
Mon, 27 Aug 2001 14:02:53 -0700


Update of /cvsroot/python/python/dist/src/Tools/compiler/compiler
In directory usw-pr-cvs1:/tmp/cvs-serv21844

Modified Files:
	transformer.py 
Log Message:
Add lookup_name() to optimize use of stack frames

The use of com_node() introduces a lot of extra stack frames, enough
to cause a stack overflow compiling test.test_parser with the standard
interpreter recursionlimit.  The com_node() is a convenience function
that hides the dispatch details, but comes at a very high cost.  It is
more efficient to dispatch directly in the callers.  In these cases,
use lookup_node() and call the dispatched node directly.

Also handle yield_stmt in a way that will work with Python 2.1
(suggested by Shane Hathaway)


Index: transformer.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Tools/compiler/compiler/transformer.py,v
retrieving revision 1.22
retrieving revision 1.23
diff -C2 -d -r1.22 -r1.23
*** transformer.py	2001/08/18 00:04:31	1.22
--- transformer.py	2001/08/27 21:02:51	1.23
***************
*** 275,279 ****
      def expr_stmt(self, nodelist):
          # augassign testlist | testlist ('=' testlist)*
!         exprNode = self.com_node(nodelist[-1])
          if len(nodelist) == 1:
              n = Discard(exprNode)
--- 275,280 ----
      def expr_stmt(self, nodelist):
          # augassign testlist | testlist ('=' testlist)*
!         en = nodelist[-1]
!         exprNode = self.lookup_node(en)(en[1:])
          if len(nodelist) == 1:
              n = Discard(exprNode)
***************
*** 697,700 ****
--- 698,712 ----
      #
  
+     # The use of com_node() introduces a lot of extra stack frames,
+     # enough to cause a stack overflow compiling test.test_parser with
+     # the standard interpreter recursionlimit.  The com_node() is a
+     # convenience function that hides the dispatch details, but comes
+     # at a very high cost.  It is more efficient to dispatch directly
+     # in the callers.  In these cases, use lookup_node() and call the
+     # dispatched node directly.
+ 
+     def lookup_node(self, node):
+         return self._dispatch[node[0]]
+ 
      def com_node(self, node):
          # Note: compile.c has handling in com_node for del_stmt, pass_stmt,
***************
*** 939,950 ****
          l = len(nodelist)
          if l == 1:
!             return self.com_node(nodelist[0])
          items = []
          for i in range(0, l, 2):
!             items.append(self.com_node(nodelist[i]))
          return constructor(items)
  
      def com_stmt(self, node):
!         result = self.com_node(node)
          assert result is not None
          if isinstance(result, Stmt):
--- 951,964 ----
          l = len(nodelist)
          if l == 1:
!             n = nodelist[0]
!             return self.lookup_node(n)(n[1:])
          items = []
          for i in range(0, l, 2):
!             n = nodelist[i]
!             items.append(self.lookup_node(n)(n[1:]))
          return constructor(items)
  
      def com_stmt(self, node):
!         result = self.lookup_node(node)(node[1:])
          assert result is not None
          if isinstance(result, Stmt):
***************
*** 1255,1259 ****
      symbol.return_stmt,
      symbol.raise_stmt,
-     symbol.yield_stmt,
      symbol.import_stmt,
      symbol.global_stmt,
--- 1269,1272 ----
***************
*** 1281,1284 ****
--- 1294,1300 ----
      symbol.atom,
      ]
+ 
+ if hasattr(symbol, 'yield_stmt'):
+     _legal_node_types.append(symbol.yield_stmt)
  
  _assign_types = [