[pypy-commit] pypy default: merged upstream.
alex_gaynor
noreply at buildbot.pypy.org
Mon Sep 5 19:03:11 CEST 2011
Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch:
Changeset: r47086:4d04034495ce
Date: 2011-09-05 09:12 -0700
http://bitbucket.org/pypy/pypy/changeset/4d04034495ce/
Log: merged upstream.
diff --git a/lib_pypy/_elementtree.py b/lib_pypy/_elementtree.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_elementtree.py
@@ -0,0 +1,6 @@
+# Just use ElementTree.
+
+from xml.etree import ElementTree
+
+globals().update(ElementTree.__dict__)
+del __all__
diff --git a/lib_pypy/stackless.py b/lib_pypy/stackless.py
--- a/lib_pypy/stackless.py
+++ b/lib_pypy/stackless.py
@@ -4,121 +4,124 @@
Please refer to their documentation.
"""
-DEBUG = True
-
-def dprint(*args):
- for arg in args:
- print arg,
- print
import traceback
-import sys
+import _continuation
+from functools import partial
+
+class TaskletExit(Exception):
+ pass
+
+CoroutineExit = TaskletExit
+
+class GWrap(_continuation.continulet):
+ """This is just a wrapper around continulet to allow
+ to stick additional attributes to a continulet.
+ To be more concrete, we need a backreference to
+ the coroutine object"""
+
+
+class coroutine(object):
+ "we can't have continulet as a base, because continulets can't be rebound"
+
+ def __init__(self):
+ self._frame = None
+ self.is_zombie = False
+
+ def __getattr__(self, attr):
+ return getattr(self._frame, attr)
+
+ def __del__(self):
+ self.is_zombie = True
+ del self._frame
+ self._frame = None
+
+ def bind(self, func, *argl, **argd):
+ """coro.bind(f, *argl, **argd) -> None.
+ binds function f to coro. f will be called with
+ arguments *argl, **argd
+ """
+ if self._frame is None or not self._frame.is_pending():
+
+ def _func(c, *args, **kwargs):
+ return func(*args, **kwargs)
+
+ run = partial(_func, *argl, **argd)
+ self._frame = frame = GWrap(run)
+ else:
+ raise ValueError("cannot bind a bound coroutine")
+
+ def switch(self):
+ """coro.switch() -> returnvalue
+ switches to coroutine coro. If the bound function
+ f finishes, the returnvalue is that of f, otherwise
+ None is returned
+ """
+ current = _getcurrent()
+ current._jump_to(self)
+
+ def _jump_to(self, coroutine):
+ _tls.current_coroutine = coroutine
+ self._frame.switch(to=coroutine._frame)
+
+ def kill(self):
+ """coro.kill() : kill coroutine coro"""
+ _tls.current_coroutine = self
+ self._frame.throw(CoroutineExit)
+
+ def _is_alive(self):
+ if self._frame is None:
+ return False
+ return not self._frame.is_pending()
+ is_alive = property(_is_alive)
+ del _is_alive
+
+ def getcurrent():
+ """coroutine.getcurrent() -> the currently running coroutine"""
+ try:
+ return _getcurrent()
+ except AttributeError:
+ return _maincoro
+ getcurrent = staticmethod(getcurrent)
+
+ def __reduce__(self):
+ raise TypeError, 'pickling is not possible based upon continulets'
+
+
+def _getcurrent():
+ "Returns the current coroutine (i.e. the one which called this function)."
+ try:
+ return _tls.current_coroutine
+ except AttributeError:
+ # first call in this thread: current == main
+ _coroutine_create_main()
+ return _tls.current_coroutine
+
try:
- # If _stackless can be imported then TaskletExit and CoroutineExit are
- # automatically added to the builtins.
- from _stackless import coroutine, greenlet
-except ImportError: # we are running from CPython
- from greenlet import greenlet, GreenletExit
- TaskletExit = CoroutineExit = GreenletExit
- del GreenletExit
- try:
- from functools import partial
- except ImportError: # we are not running python 2.5
- class partial(object):
- # just enough of 'partial' to be usefull
- def __init__(self, func, *argl, **argd):
- self.func = func
- self.argl = argl
- self.argd = argd
+ from thread import _local
+except ImportError:
+ class _local(object): # assume no threads
+ pass
- def __call__(self):
- return self.func(*self.argl, **self.argd)
+_tls = _local()
- class GWrap(greenlet):
- """This is just a wrapper around greenlets to allow
- to stick additional attributes to a greenlet.
- To be more concrete, we need a backreference to
- the coroutine object"""
+def _coroutine_create_main():
+ # create the main coroutine for this thread
+ _tls.current_coroutine = None
+ main_coroutine = coroutine()
+ main_coroutine.bind(lambda x:x)
+ _tls.main_coroutine = main_coroutine
+ _tls.current_coroutine = main_coroutine
+ return main_coroutine
- class MWrap(object):
- def __init__(self,something):
- self.something = something
- def __getattr__(self, attr):
- return getattr(self.something, attr)
+_maincoro = _coroutine_create_main()
- class coroutine(object):
- "we can't have greenlet as a base, because greenlets can't be rebound"
-
- def __init__(self):
- self._frame = None
- self.is_zombie = False
-
- def __getattr__(self, attr):
- return getattr(self._frame, attr)
-
- def __del__(self):
- self.is_zombie = True
- del self._frame
- self._frame = None
-
- def bind(self, func, *argl, **argd):
- """coro.bind(f, *argl, **argd) -> None.
- binds function f to coro. f will be called with
- arguments *argl, **argd
- """
- if self._frame is None or self._frame.dead:
- self._frame = frame = GWrap()
- frame.coro = self
- if hasattr(self._frame, 'run') and self._frame.run:
- raise ValueError("cannot bind a bound coroutine")
- self._frame.run = partial(func, *argl, **argd)
-
- def switch(self):
- """coro.switch() -> returnvalue
- switches to coroutine coro. If the bound function
- f finishes, the returnvalue is that of f, otherwise
- None is returned
- """
- try:
- return greenlet.switch(self._frame)
- except TypeError, exp: # self._frame is the main coroutine
- return greenlet.switch(self._frame.something)
-
- def kill(self):
- """coro.kill() : kill coroutine coro"""
- self._frame.throw()
-
- def _is_alive(self):
- if self._frame is None:
- return False
- return not self._frame.dead
- is_alive = property(_is_alive)
- del _is_alive
-
- def getcurrent():
- """coroutine.getcurrent() -> the currently running coroutine"""
- try:
- return greenlet.getcurrent().coro
- except AttributeError:
- return _maincoro
- getcurrent = staticmethod(getcurrent)
-
- def __reduce__(self):
- raise TypeError, 'pickling is not possible based upon greenlets'
-
- _maincoro = coroutine()
- maingreenlet = greenlet.getcurrent()
- _maincoro._frame = frame = MWrap(maingreenlet)
- frame.coro = _maincoro
- del frame
- del maingreenlet
from collections import deque
import operator
-__all__ = 'run getcurrent getmain schedule tasklet channel coroutine \
- greenlet'.split()
+__all__ = 'run getcurrent getmain schedule tasklet channel coroutine'.split()
_global_task_id = 0
_squeue = None
@@ -131,7 +134,8 @@
def _scheduler_remove(value):
try:
del _squeue[operator.indexOf(_squeue, value)]
- except ValueError:pass
+ except ValueError:
+ pass
def _scheduler_append(value, normal=True):
if normal:
diff --git a/pypy/jit/backend/llsupport/regalloc.py b/pypy/jit/backend/llsupport/regalloc.py
--- a/pypy/jit/backend/llsupport/regalloc.py
+++ b/pypy/jit/backend/llsupport/regalloc.py
@@ -57,11 +57,13 @@
all_regs = []
no_lower_byte_regs = []
save_around_call_regs = []
-
+ frame_reg = None
+
def __init__(self, longevity, frame_manager=None, assembler=None):
self.free_regs = self.all_regs[:]
self.longevity = longevity
self.reg_bindings = {}
+ self.bindings_to_frame_reg = {}
self.position = -1
self.frame_manager = frame_manager
self.assembler = assembler
@@ -218,6 +220,10 @@
self.reg_bindings[v] = loc
return loc
+ def force_allocate_frame_reg(self, v):
+ """ Allocate the new variable v in the frame register."""
+ self.bindings_to_frame_reg[v] = None
+
def force_spill_var(self, var):
self._sync_var(var)
try:
@@ -236,6 +242,8 @@
try:
return self.reg_bindings[box]
except KeyError:
+ if box in self.bindings_to_frame_reg:
+ return self.frame_reg
return self.frame_manager.loc(box)
def return_constant(self, v, forbidden_vars=[], selected_reg=None):
@@ -264,8 +272,9 @@
self._check_type(v)
if isinstance(v, Const):
return self.return_constant(v, forbidden_vars, selected_reg)
-
prev_loc = self.loc(v)
+ if prev_loc is self.frame_reg and selected_reg is None:
+ return prev_loc
loc = self.force_allocate_reg(v, forbidden_vars, selected_reg,
need_lower_byte=need_lower_byte)
if prev_loc is not loc:
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -957,6 +957,7 @@
if (isinstance(from_loc, RegLoc) and from_loc.is_xmm) or (isinstance(to_loc, RegLoc) and to_loc.is_xmm):
self.mc.MOVSD(to_loc, from_loc)
else:
+ assert to_loc is not ebp
self.mc.MOV(to_loc, from_loc)
regalloc_mov = mov # legacy interface
@@ -2510,11 +2511,6 @@
genop_discard_cond_call_gc_wb_array = genop_discard_cond_call_gc_wb
- def genop_force_token(self, op, arglocs, resloc):
- # RegAlloc.consider_force_token ensures this:
- assert isinstance(resloc, RegLoc)
- self.mc.LEA_rb(resloc.value, FORCE_INDEX_OFS)
-
def not_implemented_op_discard(self, op, arglocs):
not_implemented("not implemented operation: %s" % op.getopname())
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -29,6 +29,7 @@
all_regs = [eax, ecx, edx, ebx, esi, edi]
no_lower_byte_regs = [esi, edi]
save_around_call_regs = [eax, edx, ecx]
+ frame_reg = ebp
REGLOC_TO_GCROOTMAP_REG_INDEX = {
ebx: 1,
@@ -312,8 +313,11 @@
self.fm.frame_bindings[arg] = loc
else:
if isinstance(loc, RegLoc):
- self.rm.reg_bindings[arg] = loc
- used[loc] = None
+ if loc is ebp:
+ self.rm.bindings_to_frame_reg[arg] = None
+ else:
+ self.rm.reg_bindings[arg] = loc
+ used[loc] = None
else:
self.fm.frame_bindings[arg] = loc
self.rm.free_regs = []
@@ -1358,8 +1362,8 @@
self.assembler.datablockwrapper)
def consider_force_token(self, op):
- loc = self.rm.force_allocate_reg(op.result)
- self.Perform(op, [], loc)
+ # the FORCE_TOKEN operation returns directly 'ebp'
+ self.rm.force_allocate_frame_reg(op.result)
def not_implemented_op(self, op):
not_implemented("not implemented operation: %s" % op.getopname())
diff --git a/pypy/jit/backend/x86/runner.py b/pypy/jit/backend/x86/runner.py
--- a/pypy/jit/backend/x86/runner.py
+++ b/pypy/jit/backend/x86/runner.py
@@ -119,7 +119,8 @@
setitem(index, null)
def get_latest_force_token(self):
- return self.assembler.fail_ebp + FORCE_INDEX_OFS
+ # the FORCE_TOKEN operation and this helper both return 'ebp'.
+ return self.assembler.fail_ebp
def execute_token(self, executable_token):
addr = executable_token._x86_bootstrap_code
@@ -153,8 +154,9 @@
flavor='raw', zero=True,
immortal=True)
- def force(self, addr_of_force_index):
+ def force(self, addr_of_force_token):
TP = rffi.CArrayPtr(lltype.Signed)
+ addr_of_force_index = addr_of_force_token + FORCE_INDEX_OFS
fail_index = rffi.cast(TP, addr_of_force_index)[0]
assert fail_index >= 0, "already forced!"
faildescr = self.get_fail_descr_from_number(fail_index)
@@ -164,7 +166,7 @@
# start of "no gc operation!" block
fail_index_2 = self.assembler.grab_frame_values(
bytecode,
- addr_of_force_index - FORCE_INDEX_OFS,
+ addr_of_force_token,
self.all_null_registers)
self.assembler.leave_jitted_hook()
# end of "no gc operation!" block
diff --git a/pypy/objspace/std/test/test_methodcache.py b/pypy/objspace/std/test/test_methodcache.py
--- a/pypy/objspace/std/test/test_methodcache.py
+++ b/pypy/objspace/std/test/test_methodcache.py
@@ -88,30 +88,37 @@
def test_many_names(self):
import __pypy__
- class A(object):
- foo = 5
- bar = 6
- baz = 7
- xyz = 8
- stuff = 9
- a = 10
- foobar = 11
+ for j in range(20):
+ class A(object):
+ foo = 5
+ bar = 6
+ baz = 7
+ xyz = 8
+ stuff = 9
+ a = 10
+ foobar = 11
- a = A()
- names = [name for name in A.__dict__.keys()
- if not name.startswith('_')]
- names.sort()
- names_repeated = names * 10
- result = []
- __pypy__.reset_method_cache_counter()
- for name in names_repeated:
- result.append(getattr(a, name))
- append_counter = __pypy__.method_cache_counter("append")
- names_counters = [__pypy__.method_cache_counter(name)
- for name in names]
- assert append_counter[0] >= 5 * len(names)
- for name, count in zip(names, names_counters):
- assert count[0] >= 5, str((name, count))
+ a = A()
+ names = [name for name in A.__dict__.keys()
+ if not name.startswith('_')]
+ names.sort()
+ names_repeated = names * 10
+ result = []
+ __pypy__.reset_method_cache_counter()
+ for name in names_repeated:
+ result.append(getattr(a, name))
+ append_counter = __pypy__.method_cache_counter("append")
+ names_counters = [__pypy__.method_cache_counter(name)
+ for name in names]
+ try:
+ assert append_counter[0] >= 10 * len(names) - 1
+ for name, count in zip(names, names_counters):
+ assert count == (9, 1), str((name, count))
+ break
+ except AssertionError:
+ pass
+ else:
+ raise
def test_mutating_bases(self):
class C(object):
diff --git a/pypy/rpython/module/ll_os_stat.py b/pypy/rpython/module/ll_os_stat.py
--- a/pypy/rpython/module/ll_os_stat.py
+++ b/pypy/rpython/module/ll_os_stat.py
@@ -49,19 +49,8 @@
]
N_INDEXABLE_FIELDS = 10
-# for now, check the host Python to know which st_xxx fields exist
-STAT_FIELDS = [(_name, _TYPE) for (_name, _TYPE) in ALL_STAT_FIELDS
- if hasattr(os.stat_result, _name)]
-
-STAT_FIELD_TYPES = dict(STAT_FIELDS) # {'st_xxx': TYPE}
-
-STAT_FIELD_NAMES = [_name for (_name, _TYPE) in ALL_STAT_FIELDS
- if _name in STAT_FIELD_TYPES]
-
-del _name, _TYPE
-
# For OO backends, expose only the portable fields (the first 10).
-PORTABLE_STAT_FIELDS = STAT_FIELDS[:N_INDEXABLE_FIELDS]
+PORTABLE_STAT_FIELDS = ALL_STAT_FIELDS[:N_INDEXABLE_FIELDS]
# ____________________________________________________________
#
@@ -142,17 +131,22 @@
includes = INCLUDES
)
-if sys.platform != 'win32':
+if TIMESPEC is not None:
+ class CConfig_for_timespec:
+ _compilation_info_ = compilation_info
+ TIMESPEC = TIMESPEC
+ TIMESPEC = lltype.Ptr(
+ platform.configure(CConfig_for_timespec)['TIMESPEC'])
+
+
+def posix_declaration(try_to_add=None):
+ global STAT_STRUCT
LL_STAT_FIELDS = STAT_FIELDS[:]
+ if try_to_add:
+ LL_STAT_FIELDS.append(try_to_add)
if TIMESPEC is not None:
- class CConfig_for_timespec:
- _compilation_info_ = compilation_info
- TIMESPEC = TIMESPEC
-
- TIMESPEC = lltype.Ptr(
- platform.configure(CConfig_for_timespec)['TIMESPEC'])
def _expand(lst, originalname, timespecname):
for i, (_name, _TYPE) in enumerate(lst):
@@ -178,9 +172,34 @@
class CConfig:
_compilation_info_ = compilation_info
STAT_STRUCT = platform.Struct('struct %s' % _name_struct_stat, LL_STAT_FIELDS)
- config = platform.configure(CConfig)
+ try:
+ config = platform.configure(CConfig)
+ except platform.CompilationError:
+ if try_to_add:
+ return # failed to add this field, give up
+ raise
STAT_STRUCT = lltype.Ptr(config['STAT_STRUCT'])
+ if try_to_add:
+ STAT_FIELDS.append(try_to_add)
+
+
+# This lists only the fields that have been found on the underlying platform.
+# Initially only the PORTABLE_STAT_FIELDS, but more may be added by the
+# following loop.
+STAT_FIELDS = PORTABLE_STAT_FIELDS[:]
+
+if sys.platform != 'win32':
+ posix_declaration()
+ for _i in range(len(PORTABLE_STAT_FIELDS), len(ALL_STAT_FIELDS)):
+ posix_declaration(ALL_STAT_FIELDS[_i])
+ del _i
+
+# these two global vars only list the fields defined in the underlying platform
+STAT_FIELD_TYPES = dict(STAT_FIELDS) # {'st_xxx': TYPE}
+STAT_FIELD_NAMES = [_name for (_name, _TYPE) in STAT_FIELDS]
+del _name, _TYPE
+
def build_stat_result(st):
# only for LL backends
diff --git a/pypy/rpython/module/test/test_ll_os_stat.py b/pypy/rpython/module/test/test_ll_os_stat.py
--- a/pypy/rpython/module/test/test_ll_os_stat.py
+++ b/pypy/rpython/module/test/test_ll_os_stat.py
@@ -2,6 +2,16 @@
import sys, os
import py
+
+class TestLinuxImplementation:
+ def setup_class(cls):
+ if not sys.platform.startswith('linux'):
+ py.test.skip("linux specific tests")
+
+ def test_has_all_fields(self):
+ assert ll_os_stat.STAT_FIELDS == ll_os_stat.ALL_STAT_FIELDS[:13]
+
+
class TestWin32Implementation:
def setup_class(cls):
if sys.platform != 'win32':
More information about the pypy-commit
mailing list