[pypy-svn] pypy default: merged upstream

alex_gaynor commits-noreply at bitbucket.org
Sat Apr 9 22:49:59 CEST 2011


Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: 
Changeset: r43266:a0da832ddbe4
Date: 2011-04-09 16:49 -0400
http://bitbucket.org/pypy/pypy/changeset/a0da832ddbe4/

Log:	merged upstream

diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -22,14 +22,20 @@
     return func.code
 
 class Defaults(object):
-    _immutable_fields_ = ["items[*]"]
+    _immutable_fields_ = ["items[*]", "promote"]
 
-    def __init__(self, items):
+    def __init__(self, items, promote=False):
         self.items = items
+        self.promote = promote
 
     def getitems(self):
-        ## XXX! we would like: return jit.hint(self, promote=True).items
-        ## XXX! but it gives horrible performance in some cases
+        # an idea - we want to promote only items that we know won't change
+        # too often. this is the case for builtin functions and functions
+        # with known constant defaults. Otherwise we don't want to promote
+        # this so lambda a=a won't create a new trace each time it's
+        # encountered
+        if self.promote:
+            return jit.hint(self, promote=True).items
         return self.items
 
     def getitem(self, idx):
@@ -46,14 +52,15 @@
     can_change_code = True
 
     def __init__(self, space, code, w_globals=None, defs_w=[], closure=None,
-                 forcename=None):
+                 forcename=None, promote_defs=False):
         self.space = space
         self.name = forcename or code.co_name
         self.w_doc = None   # lazily read from code.getdocstring()
         self.code = code       # Code instance
         self.w_func_globals = w_globals  # the globals dictionary
         self.closure   = closure    # normally, list of Cell instances or None
-        self.defs = Defaults(defs_w)     # wrapper around list of w_default's
+        self.defs = Defaults(defs_w, promote=promote_defs)
+        # wrapper around list of w_default's
         self.w_func_dict = None # filled out below if needed
         self.w_module = None
 
@@ -622,7 +629,8 @@
     def __init__(self, func):
         assert isinstance(func, Function)
         Function.__init__(self, func.space, func.code, func.w_func_globals,
-                          func.defs.getitems(), func.closure, func.name)
+                          func.defs.getitems(), func.closure, func.name,
+                          promote_defs=True)
         self.w_doc = func.w_doc
         self.w_func_dict = func.w_func_dict
         self.w_module = func.w_module

diff --git a/pypy/tool/jitlogparser/storage.py b/pypy/tool/jitlogparser/storage.py
--- a/pypy/tool/jitlogparser/storage.py
+++ b/pypy/tool/jitlogparser/storage.py
@@ -30,18 +30,18 @@
             self.codes[fname] = res
             return res
 
-    def disassemble_code(self, fname, startlineno):
+    def disassemble_code(self, fname, startlineno, name):
         try:
             if py.path.local(fname).check(file=False):
                 return None # cannot find source file
         except py.error.EACCES:
             return None # cannot open the file
-        key = (fname, startlineno)
+        key = (fname, startlineno, name)
         try:
             return self.disassembled_codes[key]
         except KeyError:
             codeobjs = self.load_code(fname)
-            if startlineno not in codeobjs:
+            if (startlineno, name) not in codeobjs:
                 # cannot find the code obj at this line: this can happen for
                 # various reasons, e.g. because the .py files changed since
                 # the log was produced, or because the co_firstlineno
@@ -49,7 +49,7 @@
                 # produced by gateway.applevel(), such as the ones found in
                 # nanos.py)
                 return None
-            code = codeobjs[startlineno]
+            code = codeobjs[(startlineno, name)]
             res = dis(code)
             self.disassembled_codes[key] = res
             return res

diff --git a/pypy/tool/jitlogparser/test/test_parser.py b/pypy/tool/jitlogparser/test/test_parser.py
--- a/pypy/tool/jitlogparser/test/test_parser.py
+++ b/pypy/tool/jitlogparser/test/test_parser.py
@@ -114,11 +114,11 @@
     fname = str(py.path.local(__file__).join('..', 'x.py'))
     ops = parse('''
     [i0, i1]
-    debug_merge_point("<code object f, file '%(fname)s', line 5> #9 LOAD_FAST", 0)
-    debug_merge_point("<code object f, file '%(fname)s', line 5> #12 LOAD_CONST", 0)
-    debug_merge_point("<code object f, file '%(fname)s', line 5> #22 LOAD_CONST", 0)
-    debug_merge_point("<code object f, file '%(fname)s', line 5> #28 LOAD_CONST", 0)
-    debug_merge_point("<code object f, file '%(fname)s', line 5> #6 SETUP_LOOP", 0)
+    debug_merge_point("<code object g, file '%(fname)s', line 5> #9 LOAD_FAST", 0)
+    debug_merge_point("<code object g, file '%(fname)s', line 5> #12 LOAD_CONST", 0)
+    debug_merge_point("<code object g, file '%(fname)s', line 5> #22 LOAD_CONST", 0)
+    debug_merge_point("<code object g, file '%(fname)s', line 5> #28 LOAD_CONST", 0)
+    debug_merge_point("<code object g, file '%(fname)s', line 5> #6 SETUP_LOOP", 0)
     ''' % locals())
     res = Function.from_operations(ops.operations, LoopStorage())
     assert res.linerange == (7, 9)

diff --git a/pypy/tool/jitlogparser/module_finder.py b/pypy/tool/jitlogparser/module_finder.py
--- a/pypy/tool/jitlogparser/module_finder.py
+++ b/pypy/tool/jitlogparser/module_finder.py
@@ -6,7 +6,7 @@
     more = [code]
     while more:
         next = more.pop()
-        res[next.co_firstlineno] = next
+        res[(next.co_firstlineno, next.co_name)] = next
         more += [co for co in next.co_consts
                  if isinstance(co, types.CodeType)]
     return res

diff --git a/pypy/tool/jitlogparser/parser.py b/pypy/tool/jitlogparser/parser.py
--- a/pypy/tool/jitlogparser/parser.py
+++ b/pypy/tool/jitlogparser/parser.py
@@ -107,7 +107,8 @@
                 self.bytecode_no = int(bytecode_no)
         self.operations = operations
         self.storage = storage
-        self.code = storage.disassemble_code(self.filename, self.startlineno)
+        self.code = storage.disassemble_code(self.filename, self.startlineno,
+                                             self.name)
 
     def repr(self):
         if self.filename is None:


More information about the Pypy-commit mailing list