[Python-checkins] r86741 - python/branches/dmalcolm-ast-optimization-branch/Lib/__optimizer__.py

david.malcolm python-checkins at python.org
Thu Nov 25 00:29:26 CET 2010


Author: david.malcolm
Date: Thu Nov 25 00:29:26 2010
New Revision: 86741

Log:
Synthesize the "self" actual param when inlining method calls


Modified:
   python/branches/dmalcolm-ast-optimization-branch/Lib/__optimizer__.py

Modified: python/branches/dmalcolm-ast-optimization-branch/Lib/__optimizer__.py
==============================================================================
--- python/branches/dmalcolm-ast-optimization-branch/Lib/__optimizer__.py	(original)
+++ python/branches/dmalcolm-ast-optimization-branch/Lib/__optimizer__.py	Thu Nov 25 00:29:26 2010
@@ -243,6 +243,7 @@
 
     def visit_Name(self, node):
         # Replace local names with prefixed versions:
+        self.generic_visit(node)
         scope = get_scope(self.ste, node.id)
         if scope == LOCAL:
             node.id = self.varprefix + node.id
@@ -299,6 +300,35 @@
         # expression e.g. "f()()", or for other awkward cases
         return None
 
+    def _setup_args(self, ste, varprefix, funcdef, call, instance):
+        # Create assignment statements of the form:
+        #    __inline__x = expr for x
+        # for each parameter
+        # We will insert before the callsite
+
+        assignments = []
+
+        formalparams = funcdef.args.args
+        actualparams = call.args
+        if instance:
+            # Synthesize a "self" at the front of the params:
+            # Note that this must be just a load of a local name, to avoid,
+            # say, injecting a 2nd getattr:
+            assert is_read_from_local(ste, instance)
+            actualparams = [instance] + actualparams
+
+        for formal, actual in zip(formalparams, actualparams):
+            self.log('  formal: %s' % ast.dump(formal))
+            self.log('    actual: %s' % ast.dump(actual))
+            add_local(ste, varprefix+formal.arg)
+
+            assign = make_assignment(varprefix+formal.arg, actual, call)
+            assignments.append(assign)
+
+            # FIXME: these seem to be being done using LOAD_NAME/STORE_NAME; why isn't it using _FAST?
+            # aha: because they're in module scope, not within a function.
+
+        return assignments
 
     def visit_Call(self, call, path):
         # Stop inlining beyond an arbitrary cutoff
@@ -347,27 +377,18 @@
         funcdef = self.def_dict[dotted_name]
 
         self.log(ast.dump(funcdef))
-        varprefix = '__internal__inline_%s%x__' % (dotted_name.replace('.', '_'), id(call))
+        varprefix = '__internal__inline_%s%x__' % (dotted_name, id(call))
         self.log('varprefix: %s' % varprefix)
 
         # Generate a body of specialized statements that can replace the call:
-        specialized = []
-
-        # Create assignment statements of the form:
-        #    __inline__x = expr for x
-        # for each parameter
-        # We will insert before the callsite
-        for formal, actual in zip(funcdef.args.args, call.args):
-            #log('formal: %s' % ast.dump(formal))
-            #log('actual: %s' % ast.dump(actual))
-            # FIXME: ste
-            add_local(ste, varprefix+formal.arg)
-
-            assign = make_assignment(varprefix+formal.arg, actual, call)
-            specialized.append(assign)
-
-            # FIXME: these seem to be being done using LOAD_NAME/STORE_NAME; why isn't it using _FAST?
-            # aha: because they're in module scope, not within a function.
+        if isinstance(call.func, ast.Attribute):
+            attr = call.func
+            value = attr.value
+            assert isinstance(value, ast.Name) and isinstance(value.ctx, ast.Load)
+            instance = value
+        else:
+            instance = None
+        specialized = self._setup_args(ste, varprefix, funcdef, call, instance)
 
         # Introduce __returnval__; initialize it to None, equivalent to
         # implicit "return None" if there are no "Return" nodes:
@@ -398,6 +419,10 @@
                                                         ctx=ast.Load()),
                                                call)
 
+        self.log('  specialized:')
+        for stmt in specialized:
+            self.log('    %s' % ast.dump(stmt))
+
         return ast.copy_location(ast.Specialize(name=call.func,
                                                 expected_value='__internal__.saved.' + dotted_name,
                                                 generalized=call,
@@ -760,7 +785,7 @@
 
     def log(self, msg):
         if 0:
-            print(msg)
+            print('%s: %s' % (self.__class__.__name__, msg))
 
     def visit_FunctionDef(self, funcdef, path):
         self.log('got function def: %r' % funcdef.name)
@@ -844,7 +869,8 @@
             print('Exception during optimization of %r' % filename)
             # dot_to_png(dot_before, 'before.png')
             raise
-    #print('finished optimizing')
-    #if filename == 'optimizable.py':
-    #    print(ast.dump(t))
+    if 0:
+        print('finished optimizing')
+        if filename == 'optimizable.py':
+            print(ast.dump(t))
     return t


More information about the Python-checkins mailing list