[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