[pypy-svn] r68926 - in pypy/trunk/pypy: interpreter interpreter/astcompiler interpreter/test module/pypyjit module/pypyjit/test objspace/std

cfbolz at codespeak.net cfbolz at codespeak.net
Tue Nov 3 10:24:28 CET 2009


Author: cfbolz
Date: Tue Nov  3 10:24:27 2009
New Revision: 68926

Modified:
   pypy/trunk/pypy/interpreter/astcompiler/consts.py
   pypy/trunk/pypy/interpreter/pycode.py
   pypy/trunk/pypy/interpreter/test/test_code.py
   pypy/trunk/pypy/module/pypyjit/interp_jit.py
   pypy/trunk/pypy/module/pypyjit/test/test_can_inline.py
   pypy/trunk/pypy/objspace/std/celldict.py
   pypy/trunk/pypy/objspace/std/marshal_impl.py
Log:
Add two new flags to code objects: CO_CONTAINSLOOP, CO_CONTAINSGLOBALS.
CO_CONTAINSLOOP is used by the JIT to figure out which functions to inline
without having to go over the bytecode every time again. CO_CONTAINSGLOBALS is
used by the celldict implementation to check whether the function contains a
LOAD_GLOBAL or LOAD_NAME. If neither is there, executing the function can
proceed without finding the globals cache.


Modified: pypy/trunk/pypy/interpreter/astcompiler/consts.py
==============================================================================
--- pypy/trunk/pypy/interpreter/astcompiler/consts.py	(original)
+++ pypy/trunk/pypy/interpreter/astcompiler/consts.py	Tue Nov  3 10:24:27 2009
@@ -9,6 +9,8 @@
 CO_NESTED = 0x0010
 CO_GENERATOR = 0x0020
 CO_NOFREE = 0x0040
+CO_CONTAINSLOOP = 0x0080
+CO_CONTAINSGLOBALS = 0x0800
 CO_GENERATOR_ALLOWED = 0x1000
 CO_FUTURE_DIVISION = 0x2000
 CO_FUTURE_ABSOLUTE_IMPORT = 0x4000

Modified: pypy/trunk/pypy/interpreter/pycode.py
==============================================================================
--- pypy/trunk/pypy/interpreter/pycode.py	(original)
+++ pypy/trunk/pypy/interpreter/pycode.py	Tue Nov  3 10:24:27 2009
@@ -11,23 +11,20 @@
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.gateway import NoneNotWrapped 
 from pypy.interpreter.baseobjspace import ObjSpace, W_Root
+from pypy.interpreter.astcompiler.consts import (CO_OPTIMIZED,
+    CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS, CO_NESTED,
+    CO_GENERATOR, CO_CONTAINSLOOP, CO_CONTAINSGLOBALS)
 from pypy.rlib.rarithmetic import intmask
 from pypy.rlib.debug import make_sure_not_resized, make_sure_not_modified
 from pypy.rlib import jit
 from pypy.rlib.objectmodel import compute_hash
+from pypy.tool.stdlib_opcode import opcodedesc, HAVE_ARGUMENT
 
 # helper
 
 def unpack_str_tuple(space,w_str_tuple):
     return [space.str_w(w_el) for w_el in space.unpackiterable(w_str_tuple)]
 
-# code object contants, for co_flags below
-CO_OPTIMIZED    = 0x0001
-CO_NEWLOCALS    = 0x0002
-CO_VARARGS      = 0x0004
-CO_VARKEYWORDS  = 0x0008
-CO_NESTED       = 0x0010
-CO_GENERATOR    = 0x0020
 
 # Magic numbers for the bytecode version in code objects.
 # See comments in pypy/module/__builtin__/importing.
@@ -87,6 +84,7 @@
         self._initialize()
 
     def _initialize(self):
+        self._init_flags()
         # Precompute what arguments need to be copied into cellvars
         self._args_as_cellvars = []
         
@@ -123,6 +121,24 @@
             from pypy.objspace.std.celldict import init_code
             init_code(self)
 
+    def _init_flags(self):
+        co_code = self.co_code
+        next_instr = 0
+        while next_instr < len(co_code):
+            opcode = ord(co_code[next_instr])
+            next_instr += 1
+            if opcode >= HAVE_ARGUMENT:
+                next_instr += 2
+            while opcode == opcodedesc.EXTENDED_ARG.index:
+                opcode = ord(co_code[next_instr])
+                next_instr += 3
+            if opcode == opcodedesc.JUMP_ABSOLUTE.index:
+                self.co_flags |= CO_CONTAINSLOOP
+            elif opcode == opcodedesc.LOAD_GLOBAL.index:
+                self.co_flags |= CO_CONTAINSGLOBALS
+            elif opcode == opcodedesc.LOAD_NAME.index:
+                self.co_flags |= CO_CONTAINSGLOBALS
+
     co_names = property(lambda self: [self.space.unwrap(w_name) for w_name in self.co_names_w]) # for trace
 
     def signature(self):
@@ -163,18 +179,6 @@
                       list(code.co_cellvars),
                       hidden_applevel, cpython_magic)
 
-    def _code_new_w(space, argcount, nlocals, stacksize, flags,
-                    code, consts, names, varnames, filename,
-                    name, firstlineno, lnotab, freevars, cellvars,
-                    hidden_applevel=False):
-        """Initialize a new code objects from parameters given by
-        the pypy compiler"""
-        return PyCode(space, argcount, nlocals, stacksize, flags, code,
-                      consts[:], names, varnames, filename, name, firstlineno,
-                      lnotab, freevars, cellvars, hidden_applevel)
-
-    _code_new_w = staticmethod(_code_new_w)
-
     
     def _compute_flatcall(self):
         # Speed hack!

Modified: pypy/trunk/pypy/interpreter/test/test_code.py
==============================================================================
--- pypy/trunk/pypy/interpreter/test/test_code.py	(original)
+++ pypy/trunk/pypy/interpreter/test/test_code.py	Tue Nov  3 10:24:27 2009
@@ -188,3 +188,31 @@
         # CO_NESTED
         assert f(4).func_code.co_flags & 0x10
         assert f.func_code.co_flags & 0x10 == 0
+        # check for CO_CONTAINSLOOP
+        assert not f.func_code.co_flags & 0x0080
+        # check for CO_CONTAINSGLOBALS
+        assert not f.func_code.co_flags & 0x0800
+
+
+        exec """if 1:
+        def f():
+            return [l for l in range(100)]
+        def g():
+            return [l for l in [1, 2, 3, 4]]
+"""
+
+        # check for CO_CONTAINSLOOP
+        assert f.func_code.co_flags & 0x0080
+        assert g.func_code.co_flags & 0x0080
+        # check for CO_CONTAINSGLOBALS
+        assert f.func_code.co_flags & 0x0800
+        assert not g.func_code.co_flags & 0x0800
+
+        exec """if 1:
+        b = 2
+        def f(x):
+            exec "a = 1";
+            return a + b + x
+"""
+        # check for CO_CONTAINSGLOBALS
+        assert f.func_code.co_flags & 0x0800

Modified: pypy/trunk/pypy/module/pypyjit/interp_jit.py
==============================================================================
--- pypy/trunk/pypy/module/pypyjit/interp_jit.py	(original)
+++ pypy/trunk/pypy/module/pypyjit/interp_jit.py	Tue Nov  3 10:24:27 2009
@@ -11,12 +11,11 @@
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.gateway import ObjSpace, Arguments
 from pypy.interpreter.eval import Frame
-from pypy.interpreter.pycode import PyCode, CO_VARARGS, CO_VARKEYWORDS
+from pypy.interpreter.pycode import PyCode, CO_CONTAINSLOOP
 from pypy.interpreter.pyframe import PyFrame
 from pypy.interpreter.function import Function
 from pypy.interpreter.pyopcode import ExitFrame
 from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
-from pypy.tool.stdlib_opcode import opcodedesc, HAVE_ARGUMENT
 from opcode import opmap
 from pypy.rlib.objectmodel import we_are_translated
 
@@ -28,19 +27,7 @@
 JUMP_ABSOLUTE = opmap['JUMP_ABSOLUTE']
 
 def can_inline(next_instr, bytecode):
-    co_code = bytecode.co_code
-    next_instr = 0
-    while next_instr < len(co_code):
-        opcode = ord(co_code[next_instr])
-        next_instr += 1
-        if opcode >= HAVE_ARGUMENT:
-            next_instr += 2
-        while opcode == opcodedesc.EXTENDED_ARG.index:
-            opcode = ord(co_code[next_instr])
-            next_instr += 3
-        if opcode == JUMP_ABSOLUTE:
-            return False
-    return True
+    return not bool(bytecode.co_flags & CO_CONTAINSLOOP)
 
 def get_printable_location(next_instr, bytecode):
     from pypy.tool.stdlib_opcode import opcode_method_names

Modified: pypy/trunk/pypy/module/pypyjit/test/test_can_inline.py
==============================================================================
--- pypy/trunk/pypy/module/pypyjit/test/test_can_inline.py	(original)
+++ pypy/trunk/pypy/module/pypyjit/test/test_can_inline.py	Tue Nov  3 10:24:27 2009
@@ -1,14 +1,28 @@
-
+from pypy.interpreter import pycode
 from pypy.module.pypyjit.interp_jit import can_inline
 
+class FakeSpace(object):
+    class config:
+        class objspace:
+            class std:
+                withcelldict = True
+    wrap = new_interned_str = unwrap = lambda _, x: x
+    def fromcache(self, X):
+        return X(self)
+
+
 def test_one():
+    space = FakeSpace()
     def f():
         pass
-    assert can_inline(0, f.func_code)
+    code = pycode.PyCode._from_code(space, f.func_code)
+    assert can_inline(0, code)
     def f():
         while i < 0:
             pass
-    assert not can_inline(0, f.func_code)
+    code = pycode.PyCode._from_code(space, f.func_code)
+    assert not can_inline(0, code)
     def f(a, b):
         return a + b
-    assert can_inline(0, f.func_code)
+    code = pycode.PyCode._from_code(space, f.func_code)
+    assert can_inline(0, code)

Modified: pypy/trunk/pypy/objspace/std/celldict.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/celldict.py	(original)
+++ pypy/trunk/pypy/objspace/std/celldict.py	Tue Nov  3 10:24:27 2009
@@ -1,3 +1,4 @@
+from pypy.interpreter.pycode import CO_CONTAINSGLOBALS
 from pypy.objspace.std.dictmultiobject import DictImplementation
 from pypy.objspace.std.dictmultiobject import IteratorImplementation
 from pypy.objspace.std.dictmultiobject import W_DictMultiObject, _is_sane_hash
@@ -201,14 +202,19 @@
     getcache_slow._dont_inline_ = True
 
 def init_code(code):
-    code.globalcacheholder = GlobalCacheHolder(code.space)
+    if code.co_flags & CO_CONTAINSGLOBALS:
+        code.globalcacheholder = GlobalCacheHolder(code.space)
+    else:
+        code.globalcacheholder = None
 
 
 def get_global_cache(space, code, w_globals):
     from pypy.interpreter.pycode import PyCode
     assert isinstance(code, PyCode)
     holder = code.globalcacheholder
-    return holder.getcache(space, code, w_globals)
+    if holder is not None:
+        return holder.getcache(space, code, w_globals)
+    return None
 
 def getimplementation(w_dict):
     if type(w_dict) is W_DictMultiObject:

Modified: pypy/trunk/pypy/objspace/std/marshal_impl.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/marshal_impl.py	(original)
+++ pypy/trunk/pypy/objspace/std/marshal_impl.py	Tue Nov  3 10:24:27 2009
@@ -442,9 +442,9 @@
     name        = unmarshal_str(u)
     firstlineno = u.get_int()
     lnotab      = unmarshal_str(u)
-    code = PyCode._code_new_w(space, argcount, nlocals, stacksize, flags,
-                              code, consts_w, names, varnames, filename,
-                              name, firstlineno, lnotab, freevars, cellvars)
+    code = PyCode(space, argcount, nlocals, stacksize, flags,
+                  code, consts_w[:], names, varnames, filename,
+                  name, firstlineno, lnotab, freevars, cellvars)
     return space.wrap(code)
 register(TYPE_CODE, unmarshal_pycode)
 



More information about the Pypy-commit mailing list