[pypy-commit] pypy faster-nested-scopes: merge default
cfbolz
noreply at buildbot.pypy.org
Sat Jul 16 20:22:10 CEST 2011
Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: faster-nested-scopes
Changeset: r45684:623f7c22e667
Date: 2011-07-16 20:21 +0200
http://bitbucket.org/pypy/pypy/changeset/623f7c22e667/
Log: merge default
diff --git a/pypy/doc/extending.rst b/pypy/doc/extending.rst
--- a/pypy/doc/extending.rst
+++ b/pypy/doc/extending.rst
@@ -19,12 +19,12 @@
section
* Write them in pure python and use direct libffi low-level bindings, See
- \_rawffi_ module description.
+ \_ffi_ module description.
* Write them in RPython as mixedmodule_, using *rffi* as bindings.
.. _ctypes: #CTypes
-.. _\_rawffi: #LibFFI
+.. _\_ffi: #LibFFI
.. _mixedmodule: #Mixed Modules
CTypes
@@ -42,41 +42,50 @@
platform-dependent details (compiling small snippets of C code and running
them), so it'll benefit not pypy-related ctypes-based modules as well.
+ctypes call are optimized by the JIT and the resulting machine code contains a
+direct call to the target C function. However, due to the very dynamic nature
+of ctypes, some overhead over a bare C call is still present, in particular to
+check/convert the types of the parameters. Moreover, even if most calls are
+optimized, some cannot and thus need to follow the slow path, not optimized by
+the JIT.
+
.. _`ctypes-configure`: ctypes-implementation.html#ctypes-configure
+.. _`CPython ctypes`: http://docs.python.org/library/ctypes.html
Pros
----
-Stable, CPython-compatible API
+Stable, CPython-compatible API. Most calls are fast, optimized by JIT.
Cons
----
-Only pure-python code (slow), problems with platform-dependency (although
-we partially solve those). PyPy implementation is now very slow.
+Problems with platform-dependency (although we partially solve
+those). Although the JIT optimizes ctypes calls, some overhead is still
+present. The slow-path is very slow.
-_`CPython ctypes`: http://python.net/crew/theller/ctypes/
LibFFI
======
Mostly in order to be able to write a ctypes module, we developed a very
-low-level libffi bindings. (libffi is a C-level library for dynamic calling,
+low-level libffi bindings called ``_ffi``. (libffi is a C-level library for dynamic calling,
which is used by CPython ctypes). This library provides stable and usable API,
although it's API is a very low-level one. It does not contain any
-magic.
+magic. It is also optimized by the JIT, but has much less overhead than ctypes.
Pros
----
-Works. Combines disadvantages of using ctypes with disadvantages of
-using mixed modules. Probably more suitable for a delicate code
-where ctypes magic goes in a way.
+It Works. Probably more suitable for a delicate code where ctypes magic goes
+in a way. All calls are optimized by the JIT, there is no slow path as in
+ctypes.
Cons
----
-Slow. CPython-incompatible API, very rough and low-level
+It combines disadvantages of using ctypes with disadvantages of using mixed
+modules. CPython-incompatible API, very rough and low-level.
Mixed Modules
=============
@@ -87,15 +96,15 @@
* a mixed module needs to be written in RPython, which is far more
complicated than Python (XXX link)
-* due to lack of separate compilation (as of April 2008), each
+* due to lack of separate compilation (as of July 2011), each
compilation-check requires to recompile whole PyPy python interpreter,
which takes 0.5-1h. We plan to solve this at some point in near future.
* although rpython is a garbage-collected language, the border between
C and RPython needs to be managed by hand (each object that goes into the
- C level must be explicitly freed) XXX we try to solve this
+ C level must be explicitly freed).
-Some document is available `here`_
+Some documentation is available `here`_
.. _`here`: rffi.html
diff --git a/pypy/interpreter/astcompiler/misc.py b/pypy/interpreter/astcompiler/misc.py
--- a/pypy/interpreter/astcompiler/misc.py
+++ b/pypy/interpreter/astcompiler/misc.py
@@ -27,9 +27,10 @@
_emit_syntax_warning(space, w_msg, w_filename, w_lineno, w_offset)
-def parse_future(tree):
+def parse_future(tree, feature_flags):
future_lineno = 0
future_column = 0
+ flags = 0
have_docstring = False
body = None
if isinstance(tree, ast.Module):
@@ -37,7 +38,7 @@
elif isinstance(tree, ast.Interactive):
body = tree.body
if body is None:
- return 0, 0
+ return 0, 0, 0
for stmt in body:
if isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Str):
if have_docstring:
@@ -48,11 +49,16 @@
if stmt.module == "__future__":
future_lineno = stmt.lineno
future_column = stmt.col_offset
+ for alias in stmt.names:
+ assert isinstance(alias, ast.alias)
+ # If this is an invalid flag, it will be caught later in
+ # codegen.py.
+ flags |= feature_flags.get(alias.name, 0)
else:
break
else:
break
- return future_lineno, future_column
+ return flags, future_lineno, future_column
class ForbiddenNameAssignment(Exception):
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -130,6 +130,9 @@
raise operationerrfmt(space.w_TypeError,
"cannot create weak reference to '%s' object", typename)
+ def delweakref(self):
+ pass
+
def clear_all_weakrefs(self):
"""Call this at the beginning of interp-level __del__() methods
in subclasses. It ensures that weakrefs (if any) are cleared
@@ -143,29 +146,28 @@
# app-level, e.g. a user-defined __del__(), and this code
# tries to use weakrefs again, it won't reuse the broken
# (already-cleared) weakrefs from this lifeline.
- self.setweakref(lifeline.space, None)
+ self.delweakref()
lifeline.clear_all_weakrefs()
- __already_enqueued_for_destruction = False
+ __already_enqueued_for_destruction = ()
- def _enqueue_for_destruction(self, space, call_user_del=True):
+ def enqueue_for_destruction(self, space, callback, descrname):
"""Put the object in the destructor queue of the space.
- At a later, safe point in time, UserDelAction will use
- space.userdel() to call the object's app-level __del__ method.
+ At a later, safe point in time, UserDelAction will call
+ callback(self). If that raises OperationError, prints it
+ to stderr with the descrname string.
+
+ Note that 'callback' will usually need to start with:
+ assert isinstance(self, W_SpecificClass)
"""
# this function always resurect the object, so when
# running on top of CPython we must manually ensure that
# we enqueue it only once
if not we_are_translated():
- if self.__already_enqueued_for_destruction:
+ if callback in self.__already_enqueued_for_destruction:
return
- self.__already_enqueued_for_destruction = True
- self.clear_all_weakrefs()
- if call_user_del:
- space.user_del_action.register_dying_object(self)
-
- def _call_builtin_destructor(self):
- pass # method overridden in typedef.py
+ self.__already_enqueued_for_destruction += (callback,)
+ space.user_del_action.register_callback(self, callback, descrname)
# hooks that the mapdict implementations needs:
def _get_mapdict_map(self):
diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -484,44 +484,31 @@
def __init__(self, space):
AsyncAction.__init__(self, space)
- self.dying_objects_w = []
- self.weakrefs_w = []
+ self.dying_objects = []
self.finalizers_lock_count = 0
- def register_dying_object(self, w_obj):
- self.dying_objects_w.append(w_obj)
- self.fire()
-
- def register_weakref_callback(self, w_ref):
- self.weakrefs_w.append(w_ref)
+ def register_callback(self, w_obj, callback, descrname):
+ self.dying_objects.append((w_obj, callback, descrname))
self.fire()
def perform(self, executioncontext, frame):
if self.finalizers_lock_count > 0:
return
- # Each call to perform() first grabs the self.dying_objects_w
+ # Each call to perform() first grabs the self.dying_objects
# and replaces it with an empty list. We do this to try to
# avoid too deep recursions of the kind of __del__ being called
# while in the middle of another __del__ call.
- pending_w = self.dying_objects_w
- self.dying_objects_w = []
+ pending = self.dying_objects
+ self.dying_objects = []
space = self.space
- for i in range(len(pending_w)):
- w_obj = pending_w[i]
- pending_w[i] = None
+ for i in range(len(pending)):
+ w_obj, callback, descrname = pending[i]
+ pending[i] = (None, None, None)
try:
- space.userdel(w_obj)
+ callback(w_obj)
except OperationError, e:
- e.write_unraisable(space, 'method __del__ of ', w_obj)
+ e.write_unraisable(space, descrname, w_obj)
e.clear(space) # break up reference cycles
- # finally, this calls the interp-level destructor for the
- # cases where there is both an app-level and a built-in __del__.
- w_obj._call_builtin_destructor()
- pending_w = self.weakrefs_w
- self.weakrefs_w = []
- for i in range(len(pending_w)):
- w_ref = pending_w[i]
- w_ref.activate_callback()
class FrameTraceAction(AsyncAction):
"""An action that calls the local trace functions (w_f_trace)."""
diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -114,6 +114,7 @@
def descr_close(self):
"""x.close(arg) -> raise GeneratorExit inside generator."""
+ assert isinstance(self, GeneratorIterator)
space = self.space
try:
w_retval = self.throw(space.w_GeneratorExit, space.w_None,
@@ -141,22 +142,16 @@
code_name = self.pycode.co_name
return space.wrap(code_name)
- def descr__del__(self):
- """
- applevel __del__, which is called at a safe point after the
- interp-level __del__ enqueued the object for destruction
- """
- self.descr_close()
-
def __del__(self):
# Only bother enqueuing self to raise an exception if the frame is
# still not finished and finally or except blocks are present.
- must_call_close = False
+ self.clear_all_weakrefs()
if self.frame is not None:
block = self.frame.lastblock
while block is not None:
if not isinstance(block, LoopBlock):
- must_call_close = True
+ self.enqueue_for_destruction(self.space,
+ GeneratorIterator.descr_close,
+ "interrupting generator of ")
break
block = block.previous
- self._enqueue_for_destruction(self.space, must_call_close)
diff --git a/pypy/interpreter/pycompiler.py b/pypy/interpreter/pycompiler.py
--- a/pypy/interpreter/pycompiler.py
+++ b/pypy/interpreter/pycompiler.py
@@ -119,7 +119,10 @@
raise OperationError(self.space.w_TypeError, self.space.wrap(
"invalid node type"))
- future_pos = misc.parse_future(node)
+ fut = misc.parse_future(node, self.future_flags.compiler_features)
+ f_flags, f_lineno, f_col = fut
+ future_pos = f_lineno, f_col
+ flags |= f_flags
info = pyparse.CompileInfo(filename, mode, flags, future_pos)
return self._compile_ast(node, info)
diff --git a/pypy/interpreter/test/test_typedef.py b/pypy/interpreter/test/test_typedef.py
--- a/pypy/interpreter/test/test_typedef.py
+++ b/pypy/interpreter/test/test_typedef.py
@@ -1,3 +1,4 @@
+import gc
from pypy.interpreter import typedef
from pypy.tool.udir import udir
from pypy.interpreter.baseobjspace import Wrappable
@@ -180,6 +181,85 @@
assert err.value.message == "'some_type' objects are unhashable"
""")
+ def test_destructor(self):
+ space = self.space
+ class W_Level1(Wrappable):
+ def __init__(self, space1):
+ assert space1 is space
+ def __del__(self):
+ space.call_method(w_seen, 'append', space.wrap(1))
+ class W_Level2(Wrappable):
+ def __init__(self, space1):
+ assert space1 is space
+ def __del__(self):
+ self.enqueue_for_destruction(space, W_Level2.destructormeth,
+ 'FOO ')
+ def destructormeth(self):
+ space.call_method(w_seen, 'append', space.wrap(2))
+ W_Level1.typedef = typedef.TypeDef(
+ 'level1',
+ __new__ = typedef.generic_new_descr(W_Level1))
+ W_Level2.typedef = typedef.TypeDef(
+ 'level2',
+ __new__ = typedef.generic_new_descr(W_Level2))
+ #
+ w_seen = space.newlist([])
+ W_Level1(space)
+ gc.collect(); gc.collect()
+ assert space.unwrap(w_seen) == [1]
+ #
+ w_seen = space.newlist([])
+ W_Level2(space)
+ gc.collect(); gc.collect()
+ assert space.str_w(space.repr(w_seen)) == "[]" # not called yet
+ ec = space.getexecutioncontext()
+ self.space.user_del_action.perform(ec, None)
+ assert space.unwrap(w_seen) == [2]
+ #
+ w_seen = space.newlist([])
+ self.space.appexec([self.space.gettypeobject(W_Level1.typedef)],
+ """(level1):
+ class A3(level1):
+ pass
+ A3()
+ """)
+ gc.collect(); gc.collect()
+ assert space.unwrap(w_seen) == [1]
+ #
+ w_seen = space.newlist([])
+ self.space.appexec([self.space.gettypeobject(W_Level1.typedef),
+ w_seen],
+ """(level1, seen):
+ class A4(level1):
+ def __del__(self):
+ seen.append(4)
+ A4()
+ """)
+ gc.collect(); gc.collect()
+ assert space.unwrap(w_seen) == [4, 1]
+ #
+ w_seen = space.newlist([])
+ self.space.appexec([self.space.gettypeobject(W_Level2.typedef)],
+ """(level2):
+ class A5(level2):
+ pass
+ A5()
+ """)
+ gc.collect(); gc.collect()
+ assert space.unwrap(w_seen) == [2]
+ #
+ w_seen = space.newlist([])
+ self.space.appexec([self.space.gettypeobject(W_Level2.typedef),
+ w_seen],
+ """(level2, seen):
+ class A6(level2):
+ def __del__(self):
+ seen.append(6)
+ A6()
+ """)
+ gc.collect(); gc.collect()
+ assert space.unwrap(w_seen) == [6, 2]
+
class AppTestTypeDef:
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -228,21 +228,26 @@
return self._lifeline_
def setweakref(self, space, weakreflifeline):
self._lifeline_ = weakreflifeline
+ def delweakref(self):
+ self._lifeline_ = None
add(Proto)
if "del" in features:
+ parent_destructor = getattr(supercls, '__del__', None)
+ def call_parent_del(self):
+ assert isinstance(self, subcls)
+ parent_destructor(self)
+ def call_applevel_del(self):
+ assert isinstance(self, subcls)
+ self.space.userdel(self)
class Proto(object):
def __del__(self):
- self._enqueue_for_destruction(self.space)
- # if the base class needs its own interp-level __del__,
- # we override the _call_builtin_destructor() method to invoke it
- # after the app-level destructor.
- parent_destructor = getattr(supercls, '__del__', None)
- if parent_destructor is not None:
- def _call_builtin_destructor(self):
- parent_destructor(self)
- Proto._call_builtin_destructor = _call_builtin_destructor
-
+ self.clear_all_weakrefs()
+ self.enqueue_for_destruction(self.space, call_applevel_del,
+ 'method __del__ of ')
+ if parent_destructor is not None:
+ self.enqueue_for_destruction(self.space, call_parent_del,
+ 'internal destructor of ')
add(Proto)
if "slots" in features:
@@ -630,9 +635,12 @@
return self._lifeline_
def setweakref(self, space, weakreflifeline):
self._lifeline_ = weakreflifeline
+ def delweakref(self):
+ self._lifeline_ = None
cls._lifeline_ = None
cls.getweakref = getweakref
cls.setweakref = setweakref
+ cls.delweakref = delweakref
return weakref_descr
@@ -858,8 +866,6 @@
descrmismatch='close'),
__iter__ = interp2app(GeneratorIterator.descr__iter__,
descrmismatch='__iter__'),
- __del__ = interp2app(GeneratorIterator.descr__del__,
- descrmismatch='__del__'),
gi_running = interp_attrproperty('running', cls=GeneratorIterator),
gi_frame = GetSetProperty(GeneratorIterator.descr_gi_frame),
gi_code = GetSetProperty(GeneratorIterator.descr_gi_code),
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
@@ -482,7 +482,7 @@
#
rawstart = self.materialize_loop(original_loop_token)
debug_start("jit-backend-addr")
- debug_print("Bridge out of Guard %d has address %x to %x" %
+ debug_print("bridge out of Guard %d has address %x to %x" %
(descr_number, rawstart, rawstart + codeendpos))
debug_stop("jit-backend-addr")
self._patch_stackadjust(rawstart + stackadjustpos,
diff --git a/pypy/jit/backend/x86/test/test_regloc.py b/pypy/jit/backend/x86/test/test_regloc.py
--- a/pypy/jit/backend/x86/test/test_regloc.py
+++ b/pypy/jit/backend/x86/test/test_regloc.py
@@ -24,9 +24,14 @@
assert_encodes_as(cb64, "MOV16", (r8, ebx), '\x66\x41\x89\xD8') # 11 011 000
assert_encodes_as(cb64, "MOV16", (ebx, r8), '\x66\x44\x89\xC3') # 11 000 011
assert_encodes_as(cb64, "MOV16", (ecx, ebx), '\x66\x40\x89\xD9')
- # XXX: What we are testing for here is actually not the most compact
- # encoding.
- assert_encodes_as(cb64, "MOV16", (ecx, ImmedLoc(12345)), '\x66\x40\xC7\xC1\x39\x30')
+ assert_encodes_as(cb64, "MOV16", (ecx, ImmedLoc(12345)), '\x66\xB9\x39\x30')
+ # for the next case we don't pick the most efficient encoding, but well
+ expected = '\x66\x40\xC7\xC1\xC7\xCF' # could be '\x66\xB9\xC7\xCF'
+ assert_encodes_as(cb64, "MOV16", (ecx, ImmedLoc(-12345)), expected)
+ assert_encodes_as(cb64, "MOV16", (r9, ImmedLoc(12345)), '\x66\x41\xB9\x39\x30')
+ # for the next case we don't pick the most efficient encoding, but well
+ expected = '\x66\x41\xC7\xC1\xC7\xCF' # could be '\x66\x41\xB9\xC7\xCF'
+ assert_encodes_as(cb64, "MOV16", (r9, ImmedLoc(-12345)), expected)
assert_encodes_as(cb64, "MOV16", (AddressLoc(r13, ImmedLoc(0), 0, 0), ImmedLoc(12345)), '\x66\x41\xC7\x45\x00\x39\x30')
def test_cmp_16():
@@ -44,7 +49,7 @@
def test_relocation():
from pypy.rpython.lltypesystem import lltype, rffi
from pypy.jit.backend.x86 import codebuf
- for target in [0x01020304, 0x0102030405060708]:
+ for target in [0x01020304, -0x05060708, 0x0102030405060708]:
if target > sys.maxint:
continue
mc = codebuf.MachineCodeBlockWrapper()
@@ -58,10 +63,15 @@
expected = "\xE8" + struct.pack('<i', target - (rawstart + 5))
elif IS_X86_64:
assert mc.relocations == []
- if target <= 0x7fffffff:
+ if 0 <= target <= 0xffffffff:
+ assert length == 9
+ expected = (
+ "\x41\xBB\x04\x03\x02\x01" # MOV %r11, target
+ "\x41\xFF\xD3") # CALL *%r11
+ elif -0x80000000 <= target < 0:
assert length == 10
expected = (
- "\x49\xC7\xC3\x04\x03\x02\x01" # MOV %r11, target
+ "\x49\xC7\xC3\xF8\xF8\xF9\xFA" # MOV %r11, target
"\x41\xFF\xD3") # CALL *%r11
else:
assert length == 13
diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -809,8 +809,15 @@
return self.force_cast_without_longlong(op.args[0], op.result)
def force_cast_without_longlong(self, v_arg, v_result):
- from pypy.rpython.lltypesystem.rffi import size_and_sign, sizeof
+ from pypy.rpython.lltypesystem.rffi import size_and_sign, sizeof, FLOAT
from pypy.rlib.rarithmetic import intmask
+ #
+ if (v_result.concretetype in (FLOAT, lltype.Float) or
+ v_arg.concretetype in (FLOAT, lltype.Float)):
+ assert (v_result.concretetype == lltype.Float and
+ v_arg.concretetype == lltype.Float), "xxx unsupported cast"
+ return
+ #
size2, unsigned2 = size_and_sign(v_result.concretetype)
assert size2 <= sizeof(lltype.Signed)
if size2 == sizeof(lltype.Signed):
diff --git a/pypy/jit/codewriter/regalloc.py b/pypy/jit/codewriter/regalloc.py
--- a/pypy/jit/codewriter/regalloc.py
+++ b/pypy/jit/codewriter/regalloc.py
@@ -96,6 +96,7 @@
def _try_coalesce(self, v, w):
if isinstance(v, Variable) and getkind(v.concretetype) == self.kind:
+ assert getkind(w.concretetype) == self.kind
dg = self._depgraph
uf = self._unionfind
v0 = uf.find_rep(v)
diff --git a/pypy/jit/codewriter/test/test_flatten.py b/pypy/jit/codewriter/test/test_flatten.py
--- a/pypy/jit/codewriter/test/test_flatten.py
+++ b/pypy/jit/codewriter/test/test_flatten.py
@@ -854,6 +854,14 @@
int_return %i0
""", transform=True)
+ def test_force_cast_float(self):
+ from pypy.rpython.lltypesystem import rffi
+ def f(n):
+ return rffi.cast(lltype.Float, n)
+ self.encoding_test(f, [12.456], """
+ float_return %f0
+ """, transform=True)
+
def test_direct_ptradd(self):
from pypy.rpython.lltypesystem import rffi
def f(p, n):
diff --git a/pypy/jit/metainterp/optimizeopt/heap.py b/pypy/jit/metainterp/optimizeopt/heap.py
--- a/pypy/jit/metainterp/optimizeopt/heap.py
+++ b/pypy/jit/metainterp/optimizeopt/heap.py
@@ -73,7 +73,7 @@
assert self._lazy_setfield is None
self._cached_fields[structvalue] = fieldvalue
- def force_lazy_setfield(self, optheap):
+ def force_lazy_setfield(self, optheap, can_cache=True):
op = self._lazy_setfield
if op is not None:
# This is the way _lazy_setfield is usually reset to None.
@@ -83,12 +83,16 @@
self._cached_fields.clear()
self._lazy_setfield = None
optheap.next_optimization.propagate_forward(op)
+ if not can_cache:
+ return
# Once it is done, we can put at least one piece of information
# back in the cache: the value of this particular structure's
# field.
structvalue = optheap.getvalue(op.getarg(0))
fieldvalue = optheap.getvalue(op.getarglist()[-1])
self.remember_field_value(structvalue, fieldvalue)
+ elif not can_cache:
+ self._cached_fields.clear()
def get_reconstructed(self, optimizer, valuemap):
assert self._lazy_setfield is None
@@ -202,20 +206,9 @@
for arraydescr in effectinfo.readonly_descrs_arrays:
self.force_lazy_setarrayitem(arraydescr)
for fielddescr in effectinfo.write_descrs_fields:
- self.force_lazy_setfield(fielddescr)
- try:
- cf = self.cached_fields[fielddescr]
- cf._cached_fields.clear()
- except KeyError:
- pass
+ self.force_lazy_setfield(fielddescr, can_cache=False)
for arraydescr in effectinfo.write_descrs_arrays:
- self.force_lazy_setarrayitem(arraydescr)
- try:
- submap = self.cached_arrayitems[arraydescr]
- for cf in submap.itervalues():
- cf._cached_fields.clear()
- except KeyError:
- pass
+ self.force_lazy_setarrayitem(arraydescr, can_cache=False)
if effectinfo.check_forces_virtual_or_virtualizable():
vrefinfo = self.optimizer.metainterp_sd.virtualref_info
self.force_lazy_setfield(vrefinfo.descr_forced)
@@ -238,20 +231,20 @@
if value in cf._cached_fields:
cf._cached_fields[newvalue] = cf._cached_fields[value]
- def force_lazy_setfield(self, descr):
+ def force_lazy_setfield(self, descr, can_cache=True):
try:
cf = self.cached_fields[descr]
except KeyError:
return
- cf.force_lazy_setfield(self)
+ cf.force_lazy_setfield(self, can_cache)
- def force_lazy_setarrayitem(self, arraydescr):
+ def force_lazy_setarrayitem(self, arraydescr, can_cache=True):
try:
submap = self.cached_arrayitems[arraydescr]
except KeyError:
return
for cf in submap.values():
- cf.force_lazy_setfield(self)
+ cf.force_lazy_setfield(self, can_cache)
def fixup_guard_situation(self):
# hackish: reverse the order of the last two operations if it makes
@@ -387,7 +380,7 @@
cf.do_setfield(self, op)
else:
# variable index, so make sure the lazy setarrayitems are done
- self.force_lazy_setarrayitem(op.getdescr())
+ self.force_lazy_setarrayitem(op.getdescr(), can_cache=False)
# and then emit the operation
self.emit_operation(op)
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -1755,6 +1755,48 @@
"""
self.optimize_loop(ops, expected)
+ def test_duplicate_getarrayitem_after_setarrayitem_bug(self):
+ ops = """
+ [p0, i0, i1]
+ setarrayitem_gc(p0, 0, i0, descr=arraydescr)
+ i6 = int_add(i0, 1)
+ setarrayitem_gc(p0, i1, i6, descr=arraydescr)
+ i10 = getarrayitem_gc(p0, 0, descr=arraydescr)
+ i11 = int_add(i10, i0)
+ jump(p0, i11, i1)
+ """
+ expected = """
+ [p0, i0, i1]
+ i6 = int_add(i0, 1)
+ setarrayitem_gc(p0, 0, i0, descr=arraydescr)
+ setarrayitem_gc(p0, i1, i6, descr=arraydescr)
+ i10 = getarrayitem_gc(p0, 0, descr=arraydescr)
+ i11 = int_add(i10, i0)
+ jump(p0, i11, i1)
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_duplicate_getarrayitem_after_setarrayitem_bug2(self):
+ ops = """
+ [p0, i0, i1]
+ i2 = getarrayitem_gc(p0, 0, descr=arraydescr)
+ i6 = int_add(i0, 1)
+ setarrayitem_gc(p0, i1, i6, descr=arraydescr)
+ i10 = getarrayitem_gc(p0, 0, descr=arraydescr)
+ i11 = int_add(i10, i2)
+ jump(p0, i11, i1)
+ """
+ expected = """
+ [p0, i0, i1]
+ i2 = getarrayitem_gc(p0, 0, descr=arraydescr)
+ i6 = int_add(i0, 1)
+ setarrayitem_gc(p0, i1, i6, descr=arraydescr)
+ i10 = getarrayitem_gc(p0, 0, descr=arraydescr)
+ i11 = int_add(i10, i2)
+ jump(p0, i11, i1)
+ """
+ self.optimize_loop(ops, expected)
+
def test_bug_1(self):
ops = """
[i0, p1]
diff --git a/pypy/jit/metainterp/optimizeopt/util.py b/pypy/jit/metainterp/optimizeopt/util.py
--- a/pypy/jit/metainterp/optimizeopt/util.py
+++ b/pypy/jit/metainterp/optimizeopt/util.py
@@ -21,7 +21,7 @@
continue
if hasattr(Class, name_prefix + name):
opclass = resoperation.opclasses[getattr(rop, name)]
- print value, name, opclass
+ assert name in opclass.__name__
result.append((value, opclass, getattr(Class, name_prefix + name)))
return unrolling_iterable(result)
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -596,12 +596,16 @@
standard_box = self.metainterp.virtualizable_boxes[-1]
if standard_box is box:
return False
+ if box in self.metainterp.nonstandard_virtualizables:
+ return True
eqbox = self.metainterp.execute_and_record(rop.PTR_EQ, None,
box, standard_box)
eqbox = self.implement_guard_value(pc, eqbox)
isstandard = eqbox.getint()
if isstandard:
self.metainterp.replace_box(box, standard_box)
+ else:
+ self.metainterp.nonstandard_virtualizables[box] = None
return not isstandard
def _get_virtualizable_field_index(self, fielddescr):
@@ -1456,6 +1460,8 @@
self.call_pure_results = args_dict_box()
# contains boxes where the class is already known
self.known_class_boxes = {}
+ # contains frame boxes that are not virtualizables
+ self.nonstandard_virtualizables = {}
def perform_call(self, jitcode, boxes, greenkey=None):
# causes the metainterp to enter the given subfunction
@@ -1797,6 +1803,7 @@
def reached_loop_header(self, greenboxes, redboxes, resumedescr):
self.known_class_boxes = {}
+ self.nonstandard_virtualizables = {} # XXX maybe not needed?
duplicates = {}
self.remove_consts_and_duplicates(redboxes, len(redboxes),
diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -2381,7 +2381,7 @@
assert res == -2
#self.check_loops(getarrayitem_gc=0, setarrayitem_gc=0) -- xxx?
- def test_retrace_ending_up_retrazing_another_loop(self):
+ def test_retrace_ending_up_retracing_another_loop(self):
myjitdriver = JitDriver(greens = ['pc'], reds = ['n', 'i', 'sa'])
bytecode = "0+sI0+SI"
diff --git a/pypy/jit/metainterp/test/test_virtualizable.py b/pypy/jit/metainterp/test/test_virtualizable.py
--- a/pypy/jit/metainterp/test/test_virtualizable.py
+++ b/pypy/jit/metainterp/test/test_virtualizable.py
@@ -1133,6 +1133,7 @@
res = self.meta_interp(f, [10])
assert res == 55
self.check_loops(new_with_vtable=0, ptr_eq=1, everywhere=True)
+ self.check_history(ptr_eq=2)
def test_virtual_child_frame_with_arrays(self):
myjitdriver = JitDriver(greens = [], reds = ['frame'],
diff --git a/pypy/module/__builtin__/compiling.py b/pypy/module/__builtin__/compiling.py
--- a/pypy/module/__builtin__/compiling.py
+++ b/pypy/module/__builtin__/compiling.py
@@ -5,7 +5,7 @@
from pypy.interpreter.pycode import PyCode
from pypy.interpreter.error import OperationError
from pypy.interpreter.astcompiler import consts, ast
-from pypy.interpreter.gateway import NoneNotWrapped, unwrap_spec
+from pypy.interpreter.gateway import unwrap_spec
@unwrap_spec(filename=str, mode=str, flags=int, dont_inherit=int)
def compile(space, w_source, filename, mode, flags=0, dont_inherit=0):
diff --git a/pypy/module/__builtin__/descriptor.py b/pypy/module/__builtin__/descriptor.py
--- a/pypy/module/__builtin__/descriptor.py
+++ b/pypy/module/__builtin__/descriptor.py
@@ -1,12 +1,10 @@
-
-from pypy.interpreter.typedef import TypeDef, GetSetProperty
from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.function import StaticMethod, ClassMethod
from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.objspace.descroperation import object_getattribute, object_setattr
-from pypy.interpreter.function import StaticMethod, ClassMethod
-from pypy.interpreter.typedef import GetSetProperty, descr_get_dict, \
- descr_set_dict, interp_attrproperty_w, generic_new_descr
+from pypy.interpreter.typedef import (TypeDef, interp_attrproperty_w,
+ generic_new_descr)
+from pypy.objspace.descroperation import object_getattribute
class W_Super(Wrappable):
def __init__(self, space, w_starttype, w_objtype, w_self):
diff --git a/pypy/module/__builtin__/functional.py b/pypy/module/__builtin__/functional.py
--- a/pypy/module/__builtin__/functional.py
+++ b/pypy/module/__builtin__/functional.py
@@ -4,13 +4,12 @@
"""
from pypy.interpreter.error import OperationError
-from pypy.interpreter.gateway import NoneNotWrapped, applevel
+from pypy.interpreter.gateway import NoneNotWrapped
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.typedef import TypeDef
from pypy.interpreter.baseobjspace import Wrappable
from pypy.rlib.rarithmetic import r_uint, intmask
from pypy.rlib.objectmodel import specialize
-from inspect import getsource, getfile
from pypy.rlib.rbigint import rbigint
@@ -662,7 +661,6 @@
def descr_reduce(self):
from pypy.interpreter.mixedmodule import MixedModule
- from pypy.module._pickle_support import maker # helper fns
space = self.space
w_mod = space.getbuiltinmodule('_pickle_support')
mod = space.interp_w(MixedModule, w_mod)
diff --git a/pypy/module/__builtin__/interp_classobj.py b/pypy/module/__builtin__/interp_classobj.py
--- a/pypy/module/__builtin__/interp_classobj.py
+++ b/pypy/module/__builtin__/interp_classobj.py
@@ -1,11 +1,9 @@
import new
from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.interpreter.gateway import NoneNotWrapped, applevel, interp2app
+from pypy.interpreter.gateway import interp2app
from pypy.interpreter.typedef import TypeDef, make_weakref_descr
from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.typedef import GetSetProperty, descr_get_dict
-from pypy.interpreter.typedef import descr_set_dict
-from pypy.rlib.rarithmetic import r_uint, intmask
+from pypy.interpreter.typedef import GetSetProperty, descr_get_dict, descr_set_dict
from pypy.rlib.objectmodel import compute_identity_hash
from pypy.rlib.debug import make_sure_not_resized
from pypy.rlib import jit
diff --git a/pypy/module/__builtin__/interp_memoryview.py b/pypy/module/__builtin__/interp_memoryview.py
--- a/pypy/module/__builtin__/interp_memoryview.py
+++ b/pypy/module/__builtin__/interp_memoryview.py
@@ -2,7 +2,7 @@
Implementation of the 'buffer' and 'memoryview' types.
"""
from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter import gateway, buffer
+from pypy.interpreter import buffer
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.typedef import TypeDef, GetSetProperty
from pypy.interpreter.error import OperationError
diff --git a/pypy/module/__builtin__/operation.py b/pypy/module/__builtin__/operation.py
--- a/pypy/module/__builtin__/operation.py
+++ b/pypy/module/__builtin__/operation.py
@@ -4,12 +4,10 @@
from pypy.interpreter import gateway
from pypy.interpreter.error import OperationError
-from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.interpreter.typedef import TypeDef
+from pypy.interpreter.gateway import unwrap_spec
from pypy.rlib.runicode import UNICHR
from pypy.rlib.rfloat import isnan, isinf, round_double
from pypy.rlib import rfloat
-import math
import __builtin__
NoneNotWrapped = gateway.NoneNotWrapped
diff --git a/pypy/module/__pypy__/interp_debug.py b/pypy/module/__pypy__/interp_debug.py
--- a/pypy/module/__pypy__/interp_debug.py
+++ b/pypy/module/__pypy__/interp_debug.py
@@ -1,5 +1,4 @@
-from pypy.interpreter.gateway import interp2app, NoneNotWrapped, unwrap_spec
-from pypy.interpreter.error import OperationError
+from pypy.interpreter.gateway import unwrap_spec
from pypy.rlib import debug, jit
diff --git a/pypy/module/__pypy__/interp_identitydict.py b/pypy/module/__pypy__/interp_identitydict.py
--- a/pypy/module/__pypy__/interp_identitydict.py
+++ b/pypy/module/__pypy__/interp_identitydict.py
@@ -1,6 +1,6 @@
from pypy.interpreter.error import OperationError
from pypy.interpreter.typedef import TypeDef
-from pypy.interpreter.gateway import NoneNotWrapped, interp2app, unwrap_spec
+from pypy.interpreter.gateway import interp2app
from pypy.interpreter.baseobjspace import Wrappable
class W_IdentityDict(Wrappable):
diff --git a/pypy/module/_ast/test/test_ast.py b/pypy/module/_ast/test/test_ast.py
--- a/pypy/module/_ast/test/test_ast.py
+++ b/pypy/module/_ast/test/test_ast.py
@@ -186,6 +186,11 @@
mod = self.get_ast("from __future__ import with_statement; import y; " \
"from __future__ import nested_scopes")
raises(SyntaxError, compile, mod, "<test>", "exec")
+ mod = self.get_ast("from __future__ import division\nx = 1/2")
+ co = compile(mod, "<test>", "exec")
+ ns = {}
+ exec co in ns
+ assert ns["x"] == .5
def test_field_attr_writable(self):
import _ast as ast
diff --git a/pypy/module/_codecs/interp_codecs.py b/pypy/module/_codecs/interp_codecs.py
--- a/pypy/module/_codecs/interp_codecs.py
+++ b/pypy/module/_codecs/interp_codecs.py
@@ -1,6 +1,6 @@
from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.interpreter.gateway import NoneNotWrapped, interp2app, unwrap_spec
-from pypy.rlib.rstring import StringBuilder, UnicodeBuilder
+from pypy.rlib.rstring import UnicodeBuilder
from pypy.rlib.objectmodel import we_are_translated
class CodecState(object):
diff --git a/pypy/module/_ffi/interp_ffi.py b/pypy/module/_ffi/interp_ffi.py
--- a/pypy/module/_ffi/interp_ffi.py
+++ b/pypy/module/_ffi/interp_ffi.py
@@ -1,9 +1,8 @@
-import sys
-from pypy.interpreter.baseobjspace import Wrappable, Arguments
+from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.error import OperationError, wrap_oserror, \
operationerrfmt
-from pypy.interpreter.gateway import interp2app, NoneNotWrapped, unwrap_spec
-from pypy.interpreter.typedef import TypeDef, GetSetProperty
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+from pypy.interpreter.typedef import TypeDef
from pypy.module._rawffi.structure import W_StructureInstance, W_Structure
#
from pypy.rpython.lltypesystem import lltype, rffi
@@ -16,7 +15,7 @@
class W_FFIType(Wrappable):
_immutable_fields_ = ['name', 'ffitype', 'w_datashape', 'w_pointer_to']
-
+
def __init__(self, name, ffitype, w_datashape=None, w_pointer_to=None):
self.name = name
self.ffitype = ffitype
@@ -83,7 +82,6 @@
def build_ffi_types():
- from pypy.rlib.clibffi import FFI_TYPE_P
types = [
# note: most of the type name directly come from the C equivalent,
# with the exception of bytes: in C, ubyte and char are equivalent,
@@ -161,7 +159,7 @@
class W_FuncPtr(Wrappable):
_immutable_fields_ = ['func', 'argtypes_w[*]', 'w_restype']
-
+
def __init__(self, func, argtypes_w, w_restype):
self.func = func
self.argtypes_w = argtypes_w
@@ -207,7 +205,7 @@
argchain.arg_singlefloat(space.float_w(w_arg))
elif w_argtype.is_struct():
# arg_raw directly takes value to put inside ll_args
- w_arg = space.interp_w(W_StructureInstance, w_arg)
+ w_arg = space.interp_w(W_StructureInstance, w_arg)
ptrval = w_arg.ll_buffer
argchain.arg_raw(ptrval)
else:
@@ -404,7 +402,7 @@
except KeyError:
raise operationerrfmt(space.w_AttributeError,
"No symbol %s found in library %s", name, self.name)
-
+
return W_FuncPtr(func, argtypes_w, w_restype)
@unwrap_spec(name=str)
diff --git a/pypy/module/_file/interp_file.py b/pypy/module/_file/interp_file.py
--- a/pypy/module/_file/interp_file.py
+++ b/pypy/module/_file/interp_file.py
@@ -43,11 +43,17 @@
# assume that the file and stream objects are only visible in the
# thread that runs __del__, so no race condition should be possible
self.clear_all_weakrefs()
+ if self.stream is not None:
+ self.enqueue_for_destruction(self.space, W_File.destructor,
+ 'close() method of ')
+
+ def destructor(self):
+ assert isinstance(self, W_File)
try:
self.direct_close()
except StreamErrors, e:
operr = wrap_streamerror(self.space, e, self.w_name)
- operr.write_unraisable(self.space, '__del__ of ', self)
+ raise operr
def fdopenstream(self, stream, fd, mode, w_name=None):
self.fd = fd
diff --git a/pypy/module/_file/interp_stream.py b/pypy/module/_file/interp_stream.py
--- a/pypy/module/_file/interp_stream.py
+++ b/pypy/module/_file/interp_stream.py
@@ -3,12 +3,10 @@
from pypy.rlib.streamio import StreamErrors
from pypy.interpreter.error import OperationError, wrap_oserror2
-from pypy.interpreter.gateway import ObjSpace
-from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.baseobjspace import ObjSpace, Wrappable
from pypy.interpreter.typedef import TypeDef
from pypy.interpreter.gateway import interp2app
-import os
def wrap_streamerror(space, e, w_filename=None):
if isinstance(e, streamio.StreamError):
diff --git a/pypy/module/_io/interp_bufferedio.py b/pypy/module/_io/interp_bufferedio.py
--- a/pypy/module/_io/interp_bufferedio.py
+++ b/pypy/module/_io/interp_bufferedio.py
@@ -4,7 +4,6 @@
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.interpreter.buffer import RWBuffer
-from pypy.rpython.lltypesystem import lltype, rffi
from pypy.rlib.rstring import StringBuilder
from pypy.rlib.rarithmetic import r_longlong, intmask
from pypy.tool.sourcetools import func_renamer
diff --git a/pypy/module/_io/interp_fileio.py b/pypy/module/_io/interp_fileio.py
--- a/pypy/module/_io/interp_fileio.py
+++ b/pypy/module/_io/interp_fileio.py
@@ -1,5 +1,4 @@
-from pypy.interpreter.typedef import (
- TypeDef, interp_attrproperty, interp_attrproperty_w, GetSetProperty)
+from pypy.interpreter.typedef import TypeDef, interp_attrproperty, GetSetProperty
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.error import OperationError, wrap_oserror, wrap_oserror2
from pypy.rlib.rarithmetic import r_longlong
diff --git a/pypy/module/_io/interp_io.py b/pypy/module/_io/interp_io.py
--- a/pypy/module/_io/interp_io.py
+++ b/pypy/module/_io/interp_io.py
@@ -6,7 +6,6 @@
TypeDef, interp_attrproperty, generic_new_descr)
from pypy.module.exceptions.interp_exceptions import W_IOError
from pypy.module._io.interp_fileio import W_FileIO
-from pypy.module._io.interp_iobase import W_IOBase
from pypy.module._io.interp_textio import W_TextIOWrapper
from pypy.rpython.module.ll_os_stat import STAT_FIELD_TYPES
diff --git a/pypy/module/_io/interp_iobase.py b/pypy/module/_io/interp_iobase.py
--- a/pypy/module/_io/interp_iobase.py
+++ b/pypy/module/_io/interp_iobase.py
@@ -57,6 +57,11 @@
def __del__(self):
self.clear_all_weakrefs()
+ self.enqueue_for_destruction(self.space, W_IOBase.destructor,
+ 'internal __del__ of ')
+
+ def destructor(self):
+ assert isinstance(self, W_IOBase)
space = self.space
w_closed = space.findattr(self, space.wrap('closed'))
try:
diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py
--- a/pypy/module/_io/interp_textio.py
+++ b/pypy/module/_io/interp_textio.py
@@ -4,7 +4,7 @@
generic_new_descr)
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.interpreter.error import OperationError
from pypy.rlib.rarithmetic import intmask, r_ulonglong, r_uint
from pypy.rlib.rbigint import rbigint
from pypy.rlib.rstring import UnicodeBuilder
diff --git a/pypy/module/_locale/interp_locale.py b/pypy/module/_locale/interp_locale.py
--- a/pypy/module/_locale/interp_locale.py
+++ b/pypy/module/_locale/interp_locale.py
@@ -1,4 +1,3 @@
-from pypy.rpython.tool import rffi_platform as platform
from pypy.rlib import rposix
from pypy.rlib.rarithmetic import intmask
diff --git a/pypy/module/_minimal_curses/fficurses.py b/pypy/module/_minimal_curses/fficurses.py
--- a/pypy/module/_minimal_curses/fficurses.py
+++ b/pypy/module/_minimal_curses/fficurses.py
@@ -2,12 +2,10 @@
""" The ffi for rpython, need to be imported for side effects
"""
-import sys
from pypy.rpython.lltypesystem import rffi
from pypy.rpython.lltypesystem import lltype
from pypy.rpython.tool import rffi_platform
from pypy.rpython.extfunc import register_external
-from pypy.rpython.extregistry import ExtRegistryEntry
from pypy.module._minimal_curses import interp_curses
from pypy.translator.tool.cbuild import ExternalCompilationInfo
@@ -82,7 +80,7 @@
return res
finally:
rffi.free_charp(ll_cap)
-
+
register_external(interp_curses._curses_tigetstr, [str], str,
export_name='_curses.tigetstr', llimpl=tigetstr_llimpl)
diff --git a/pypy/module/_multibytecodec/c_codecs.py b/pypy/module/_multibytecodec/c_codecs.py
--- a/pypy/module/_multibytecodec/c_codecs.py
+++ b/pypy/module/_multibytecodec/c_codecs.py
@@ -1,4 +1,4 @@
-import py, sys
+import py
from pypy.rpython.lltypesystem import lltype, rffi
from pypy.translator.tool.cbuild import ExternalCompilationInfo
from pypy.tool.autopath import pypydir
diff --git a/pypy/module/_multibytecodec/interp_multibytecodec.py b/pypy/module/_multibytecodec/interp_multibytecodec.py
--- a/pypy/module/_multibytecodec/interp_multibytecodec.py
+++ b/pypy/module/_multibytecodec/interp_multibytecodec.py
@@ -1,5 +1,5 @@
from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.gateway import ObjSpace, interp2app, unwrap_spec
+from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.typedef import TypeDef
from pypy.interpreter.error import OperationError
from pypy.module._multibytecodec import c_codecs
diff --git a/pypy/module/_multiprocessing/interp_connection.py b/pypy/module/_multiprocessing/interp_connection.py
--- a/pypy/module/_multiprocessing/interp_connection.py
+++ b/pypy/module/_multiprocessing/interp_connection.py
@@ -4,7 +4,7 @@
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.error import (
OperationError, wrap_oserror, operationerrfmt)
-from pypy.rpython.lltypesystem import rffi, lltype, llmemory
+from pypy.rpython.lltypesystem import rffi, lltype
from pypy.rlib.rarithmetic import intmask
from pypy.rlib import rpoll
import sys
diff --git a/pypy/module/_multiprocessing/interp_semaphore.py b/pypy/module/_multiprocessing/interp_semaphore.py
--- a/pypy/module/_multiprocessing/interp_semaphore.py
+++ b/pypy/module/_multiprocessing/interp_semaphore.py
@@ -15,7 +15,6 @@
if sys.platform == 'win32':
from pypy.rlib import rwin32
- from pypy.interpreter.error import wrap_windowserror
from pypy.module._multiprocessing.interp_win32 import (
handle_w, _GetTickCount)
diff --git a/pypy/module/_pickle_support/maker.py b/pypy/module/_pickle_support/maker.py
--- a/pypy/module/_pickle_support/maker.py
+++ b/pypy/module/_pickle_support/maker.py
@@ -1,4 +1,4 @@
-from pypy.interpreter.error import OperationError
+from pypy.interpreter.error import OperationError
from pypy.interpreter.nestedscope import Cell
from pypy.interpreter.pycode import PyCode
from pypy.interpreter.function import Function, Method
@@ -8,7 +8,6 @@
from pypy.interpreter.generator import GeneratorIterator
from pypy.rlib.objectmodel import instantiate
from pypy.interpreter.gateway import unwrap_spec
-from pypy.objspace.std.dicttype import dictiter_typedef
from pypy.objspace.std.iterobject import W_SeqIterObject, W_ReverseSeqIterObject
@@ -79,7 +78,7 @@
try:
return gateway.BuiltinCode.find(identifier)
except KeyError:
- raise OperationError(space.w_RuntimeError,
+ raise OperationError(space.w_RuntimeError,
space.wrap("cannot unpickle builtin code: "+
identifier))
@@ -89,7 +88,7 @@
try:
return function.Function.find(identifier)
except KeyError:
- raise OperationError(space.w_RuntimeError,
+ raise OperationError(space.w_RuntimeError,
space.wrap("cannot unpickle builtin function: "+
identifier))
diff --git a/pypy/module/_rawffi/callback.py b/pypy/module/_rawffi/callback.py
--- a/pypy/module/_rawffi/callback.py
+++ b/pypy/module/_rawffi/callback.py
@@ -2,10 +2,10 @@
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.typedef import TypeDef, GetSetProperty
from pypy.rpython.lltypesystem import lltype, rffi
-from pypy.module._rawffi.array import get_elem, push_elem
+from pypy.module._rawffi.array import push_elem
from pypy.module._rawffi.structure import W_Structure
-from pypy.module._rawffi.interp_rawffi import W_DataInstance, letter2tp, \
- wrap_value, unwrap_value, unwrap_truncate_int, unpack_argshapes
+from pypy.module._rawffi.interp_rawffi import (W_DataInstance, letter2tp,
+ unwrap_value, unpack_argshapes)
from pypy.rlib.clibffi import USERDATA_P, CallbackFuncPtr, FUNCFLAG_CDECL
from pypy.rlib.clibffi import ffi_type_void
from pypy.rlib import rweakref
diff --git a/pypy/module/_rawffi/interp_rawffi.py b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -1,7 +1,6 @@
-import sys
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.error import OperationError, wrap_oserror, operationerrfmt
-from pypy.interpreter.gateway import interp2app, NoneNotWrapped, unwrap_spec
+from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.typedef import TypeDef, GetSetProperty
from pypy.rlib.clibffi import *
@@ -15,7 +14,7 @@
from pypy.rlib import rwin32
from pypy.tool.sourcetools import func_with_new_name
-from pypy.rlib.rarithmetic import intmask, r_uint, r_singlefloat
+from pypy.rlib.rarithmetic import intmask, r_uint
from pypy.module._rawffi.tracker import tracker
TYPEMAP = {
diff --git a/pypy/module/_socket/interp_func.py b/pypy/module/_socket/interp_func.py
--- a/pypy/module/_socket/interp_func.py
+++ b/pypy/module/_socket/interp_func.py
@@ -1,9 +1,8 @@
-from pypy.interpreter.gateway import NoneNotWrapped, unwrap_spec
+from pypy.interpreter.gateway import unwrap_spec
from pypy.module._socket.interp_socket import converted_error, W_RSocket
from pypy.rlib import rsocket
from pypy.rlib.rsocket import SocketError
-from pypy.rlib.rarithmetic import r_uint
-from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.interpreter.error import OperationError
def gethostname(space):
"""gethostname() -> string
diff --git a/pypy/module/_ssl/interp_ssl.py b/pypy/module/_ssl/interp_ssl.py
--- a/pypy/module/_ssl/interp_ssl.py
+++ b/pypy/module/_ssl/interp_ssl.py
@@ -1,7 +1,7 @@
from __future__ import with_statement
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.interpreter.error import OperationError
-from pypy.interpreter.baseobjspace import W_Root, ObjSpace, Wrappable
+from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.typedef import TypeDef
from pypy.interpreter.gateway import interp2app, unwrap_spec
@@ -11,7 +11,6 @@
from pypy.module._socket import interp_socket
-import sys
## user defined constants
X509_NAME_MAXLEN = 256
@@ -131,13 +130,13 @@
self._issuer = lltype.malloc(rffi.CCHARP.TO, X509_NAME_MAXLEN, flavor='raw')
self._issuer[0] = '\0'
self.shutdown_seen_zero = False
-
+
def server(self):
return self.space.wrap(rffi.charp2str(self._server))
-
+
def issuer(self):
return self.space.wrap(rffi.charp2str(self._issuer))
-
+
def __del__(self):
if self.peer_cert:
libssl_X509_free(self.peer_cert)
@@ -147,7 +146,7 @@
libssl_SSL_CTX_free(self.ctx)
lltype.free(self._server, flavor='raw')
lltype.free(self._issuer, flavor='raw')
-
+
@unwrap_spec(data='bufferstr')
def write(self, data):
"""write(s) -> len
@@ -230,10 +229,10 @@
raw_buf, gc_buf = rffi.alloc_buffer(num_bytes)
while True:
err = 0
-
+
count = libssl_SSL_read(self.ssl, raw_buf, num_bytes)
err = libssl_SSL_get_error(self.ssl, count)
-
+
if err == SSL_ERROR_WANT_READ:
sockstate = check_socket_and_wait_for_timeout(self.space,
self.w_socket, False)
@@ -245,17 +244,17 @@
return self.space.wrap("")
else:
sockstate = SOCKET_OPERATION_OK
-
+
if sockstate == SOCKET_HAS_TIMED_OUT:
raise ssl_error(self.space, "The read operation timed out")
elif sockstate == SOCKET_IS_NONBLOCKING:
break
-
+
if err == SSL_ERROR_WANT_READ or err == SSL_ERROR_WANT_WRITE:
continue
else:
break
-
+
if count <= 0:
raise _ssl_seterror(self.space, self, count)
@@ -351,7 +350,7 @@
self.shutdown_seen_zero = True
continue
- # Possibly retry shutdown until timeout or failure
+ # Possibly retry shutdown until timeout or failure
ssl_err = libssl_SSL_get_error(self.ssl, ret)
if ssl_err == SSL_ERROR_WANT_READ:
sockstate = check_socket_and_wait_for_timeout(
@@ -397,7 +396,7 @@
else:
w_proto = space.w_None
- bits = libssl_SSL_CIPHER_get_bits(current,
+ bits = libssl_SSL_CIPHER_get_bits(current,
lltype.nullptr(rffi.INTP.TO))
w_bits = space.newint(bits)
@@ -552,7 +551,7 @@
ext = libssl_X509_get_ext(certificate, i)
method = libssl_X509V3_EXT_get(ext)
if not method:
- raise ssl_error(space,
+ raise ssl_error(space,
"No method for internalizing subjectAltName!'")
with lltype.scoped_alloc(rffi.CCHARPP.TO, 1) as p_ptr:
@@ -858,7 +857,7 @@
cert = libssl_BIO_new(libssl_BIO_s_file())
if not cert:
raise ssl_error(space, "Can't malloc memory to read file")
-
+
try:
if libssl_BIO_read_filename(cert, filename) <= 0:
raise ssl_error(space, "Can't open file")
@@ -873,7 +872,7 @@
libssl_X509_free(x)
finally:
libssl_BIO_free(cert)
-
+
# this function is needed to perform locking on shared data
# structures. (Note that OpenSSL uses a number of global data
# structures that will be implicitly shared whenever multiple threads
diff --git a/pypy/module/_stackless/interp_coroutine.py b/pypy/module/_stackless/interp_coroutine.py
--- a/pypy/module/_stackless/interp_coroutine.py
+++ b/pypy/module/_stackless/interp_coroutine.py
@@ -15,13 +15,10 @@
experience to decide where to set the limits.
"""
-from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.argument import Arguments
from pypy.interpreter.typedef import GetSetProperty, TypeDef
-from pypy.interpreter.typedef import interp_attrproperty, interp_attrproperty_w
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.interpreter.function import StaticMethod
from pypy.module._stackless.stackless_flags import StacklessFlags
from pypy.module._stackless.rcoroutine import Coroutine, BaseCoState, AbstractThunk, CoroutineExit
@@ -38,7 +35,7 @@
self.costate = costate
if not space.is_true(space.callable(w_obj)):
raise operationerrfmt(
- space.w_TypeError,
+ space.w_TypeError,
"'%s' object is not callable",
space.type(w_obj).getname(space))
self.w_func = w_obj
@@ -65,7 +62,7 @@
# Should be moved to interp_stackless.py if it's ever implemented... Currently
# used by pypy/lib/stackless.py.
-W_TaskletExit = _new_exception('TaskletExit', W_SystemExit,
+W_TaskletExit = _new_exception('TaskletExit', W_SystemExit,
"""Tasklet killed manually.""")
class AppCoroutine(Coroutine): # XXX, StacklessFlags):
@@ -90,7 +87,7 @@
def _get_state(space):
return space.fromcache(AppCoState)
_get_state = staticmethod(_get_state)
-
+
def w_bind(self, w_func, __args__):
space = self.space
if self.frame is not None:
@@ -127,7 +124,7 @@
w_excvalue = operror.get_w_value(space)
w_exctraceback = operror.get_traceback()
w_excinfo = space.newtuple([w_exctype, w_excvalue, w_exctraceback])
-
+
if w_exctype is self.costate.w_CoroutineExit:
self.coroutine_exit = True
else:
@@ -146,22 +143,22 @@
def w_kill(self):
self.kill()
-
+
def w_throw(self, w_type, w_value=None, w_traceback=None):
space = self.space
operror = OperationError(w_type, w_value)
operror.normalize_exception(space)
-
+
if not space.is_w(w_traceback, space.w_None):
from pypy.interpreter import pytraceback
tb = space.interpclass_w(w_traceback)
- if tb is None or not space.is_true(space.isinstance(tb,
+ if tb is None or not space.is_true(space.isinstance(tb,
space.gettypeobject(pytraceback.PyTraceback.typedef))):
raise OperationError(space.w_TypeError,
space.wrap("throw: arg 3 must be a traceback or None"))
operror.set_traceback(tb)
-
+
self._kill(operror)
def _userdel(self):
@@ -280,7 +277,7 @@
assert isinstance(w_klass, W_TypeObject)
old_flag = w_klass.flag_heaptype
w_klass.flag_heaptype = True
-
+
space.appexec([w_klass, space.wrap(funcname)], """
(klass, funcname):
func = getattr(klass, funcname)
@@ -332,23 +329,23 @@
# Exporting new exception to space
self.w_CoroutineExit = space.gettypefor(W_CoroutineExit)
space.setitem(
- space.exceptions_module.w_dict,
- space.new_interned_str('CoroutineExit'),
- self.w_CoroutineExit)
- space.setitem(space.builtin.w_dict,
- space.new_interned_str('CoroutineExit'),
+ space.exceptions_module.w_dict,
+ space.new_interned_str('CoroutineExit'),
self.w_CoroutineExit)
-
+ space.setitem(space.builtin.w_dict,
+ space.new_interned_str('CoroutineExit'),
+ self.w_CoroutineExit)
+
# Should be moved to interp_stackless.py if it's ever implemented...
self.w_TaskletExit = space.gettypefor(W_TaskletExit)
space.setitem(
- space.exceptions_module.w_dict,
- space.new_interned_str('TaskletExit'),
- self.w_TaskletExit)
- space.setitem(space.builtin.w_dict,
- space.new_interned_str('TaskletExit'),
- self.w_TaskletExit)
-
+ space.exceptions_module.w_dict,
+ space.new_interned_str('TaskletExit'),
+ self.w_TaskletExit)
+ space.setitem(space.builtin.w_dict,
+ space.new_interned_str('TaskletExit'),
+ self.w_TaskletExit)
+
def post_install(self):
self.current = self.main = AppCoroutine(self.space, state=self)
self.main.subctx.clear_framestack() # wack
@@ -378,7 +375,7 @@
instr = frame.last_instr
opcode = ord(code[instr])
map = pythonopcode.opmap
- call_ops = [map['CALL_FUNCTION'], map['CALL_FUNCTION_KW'], map['CALL_FUNCTION_VAR'],
+ call_ops = [map['CALL_FUNCTION'], map['CALL_FUNCTION_KW'], map['CALL_FUNCTION_VAR'],
map['CALL_FUNCTION_VAR_KW'], map['CALL_METHOD']]
assert opcode in call_ops
instr += 1
diff --git a/pypy/module/_stackless/interp_stackless.py b/pypy/module/_stackless/interp_stackless.py
--- a/pypy/module/_stackless/interp_stackless.py
+++ b/pypy/module/_stackless/interp_stackless.py
@@ -1,9 +1,6 @@
from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.typedef import GetSetProperty, TypeDef
-from pypy.interpreter.typedef import interp_attrproperty, interp_attrproperty_w
+from pypy.interpreter.typedef import TypeDef
from pypy.interpreter.gateway import interp2app
-from pypy.interpreter.error import OperationError
-from pypy.rlib.rarithmetic import intmask
import os
diff --git a/pypy/module/_stackless/rclonable.py b/pypy/module/_stackless/rclonable.py
--- a/pypy/module/_stackless/rclonable.py
+++ b/pypy/module/_stackless/rclonable.py
@@ -1,7 +1,6 @@
from pypy.module._stackless.interp_coroutine import AbstractThunk, Coroutine
from pypy.rlib.rgc import gc_swap_pool, gc_clone
from pypy.rlib.objectmodel import we_are_translated
-from pypy.interpreter.error import OperationError
class InterpClonableMixin:
@@ -76,7 +75,7 @@
if not isinstance(current, InterpClonableCoroutine):
raise RuntimeError("fork() in a non-clonable coroutine")
thunk = ForkThunk(current)
- coro_fork = InterpClonableCoroutine()
+ coro_fork = InterpClonableCoroutine()
coro_fork.bind(thunk)
coro_fork.switch()
# we resume here twice. The following would need explanations about
diff --git a/pypy/module/_weakref/interp__weakref.py b/pypy/module/_weakref/interp__weakref.py
--- a/pypy/module/_weakref/interp__weakref.py
+++ b/pypy/module/_weakref/interp__weakref.py
@@ -1,16 +1,15 @@
import py
-from pypy.interpreter.argument import Arguments
from pypy.interpreter.baseobjspace import Wrappable, W_Root
from pypy.interpreter.error import OperationError
from pypy.interpreter.gateway import interp2app, ObjSpace
-from pypy.interpreter.typedef import GetSetProperty, TypeDef
+from pypy.interpreter.typedef import TypeDef
from pypy.rlib import jit
import weakref
class WeakrefLifeline(W_Root):
def __init__(self, space):
- self.space = space # this is here for W_Root.clear_all_weakrefs()
+ self.space = space
self.refs_weak = []
self.cached_weakref_index = -1
self.cached_proxy_index = -1
@@ -23,8 +22,10 @@
"""
for i in range(len(self.refs_weak) - 1, -1, -1):
w_ref = self.refs_weak[i]()
- if w_ref is not None:
- self.space.user_del_action.register_weakref_callback(w_ref)
+ if w_ref is not None and w_ref.w_callable is not None:
+ w_ref.enqueue_for_destruction(self.space,
+ W_WeakrefBase.activate_callback,
+ 'weakref callback of ')
def clear_all_weakrefs(self):
"""Clear all weakrefs. This is called when an app-level object has
@@ -118,11 +119,8 @@
self.w_obj_weak = dead_ref
def activate_callback(w_self):
- if not w_self.w_callable is None:
- try:
- w_self.space.call_function(w_self.w_callable, w_self)
- except OperationError, e:
- e.write_unraisable(w_self.space, 'weakref callback ', w_self.w_callable)
+ assert isinstance(w_self, W_WeakrefBase)
+ w_self.space.call_function(w_self.w_callable, w_self)
def descr__repr__(self, space):
w_obj = self.dereference()
diff --git a/pypy/module/_winreg/interp_winreg.py b/pypy/module/_winreg/interp_winreg.py
--- a/pypy/module/_winreg/interp_winreg.py
+++ b/pypy/module/_winreg/interp_winreg.py
@@ -1,6 +1,5 @@
from __future__ import with_statement
from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.baseobjspace import ObjSpace, W_Root
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.typedef import TypeDef, GetSetProperty
from pypy.interpreter.error import OperationError, wrap_windowserror
diff --git a/pypy/module/array/interp_array.py b/pypy/module/array/interp_array.py
--- a/pypy/module/array/interp_array.py
+++ b/pypy/module/array/interp_array.py
@@ -1,10 +1,9 @@
from __future__ import with_statement
-from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.buffer import RWBuffer
from pypy.interpreter.error import OperationError
from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.interpreter.typedef import TypeDef, GetSetProperty, make_weakref_descr
+from pypy.interpreter.typedef import GetSetProperty, make_weakref_descr
from pypy.module._file.interp_file import W_File
from pypy.objspace.std.model import W_Object
from pypy.objspace.std.multimethod import FailedToImplement
diff --git a/pypy/module/bz2/interp_bz2.py b/pypy/module/bz2/interp_bz2.py
--- a/pypy/module/bz2/interp_bz2.py
+++ b/pypy/module/bz2/interp_bz2.py
@@ -4,9 +4,8 @@
from pypy.rpython.lltypesystem import lltype
from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.typedef import TypeDef, GetSetProperty
-from pypy.interpreter.typedef import interp_attrproperty
-from pypy.interpreter.gateway import NoneNotWrapped, interp2app, unwrap_spec
+from pypy.interpreter.typedef import TypeDef, interp_attrproperty
+from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.rlib.streamio import Stream
from pypy.translator.tool.cbuild import ExternalCompilationInfo
from pypy.translator.platform import platform as compiler
@@ -67,7 +66,7 @@
'BZ_OUTBUFF_FULL', 'BZ_CONFIG_ERROR']
for name in constant_names:
setattr(CConfig, name, platform.DefinedConstantInteger(name))
-
+
class cConfig(object):
pass
for k, v in platform.configure(CConfig).items():
@@ -100,7 +99,7 @@
SMALLCHUNK = 8192
else:
SMALLCHUNK = BUFSIZ
-
+
if rffi.sizeof(rffi.INT) > 4:
BIGCHUNK = 512 * 32
else:
@@ -505,7 +504,7 @@
self.bzs = lltype.malloc(bz_stream.TO, flavor='raw', zero=True)
self.running = False
self._init_bz2comp(compresslevel)
-
+
def _init_bz2comp(self, compresslevel):
if compresslevel < 1 or compresslevel > 9:
raise OperationError(self.space.w_ValueError,
@@ -514,13 +513,13 @@
bzerror = intmask(BZ2_bzCompressInit(self.bzs, compresslevel, 0, 0))
if bzerror != BZ_OK:
_catch_bz2_error(self.space, bzerror)
-
+
self.running = True
-
+
def __del__(self):
BZ2_bzCompressEnd(self.bzs)
lltype.free(self.bzs, flavor='raw')
-
+
@unwrap_spec(data='bufferstr')
def compress(self, data):
"""compress(data) -> string
@@ -529,12 +528,12 @@
compressed data whenever possible. When you've finished providing data
to compress, call the flush() method to finish the compression process,
and return what is left in the internal buffers."""
-
+
datasize = len(data)
-
+
if datasize == 0:
return self.space.wrap("")
-
+
if not self.running:
raise OperationError(self.space.w_ValueError,
self.space.wrap("this object was already flushed"))
@@ -562,7 +561,7 @@
res = out.make_result_string()
return self.space.wrap(res)
-
+
def flush(self):
if not self.running:
raise OperationError(self.space.w_ValueError,
@@ -576,7 +575,7 @@
break
elif bzerror != BZ_FINISH_OK:
_catch_bz2_error(self.space, bzerror)
-
+
if rffi.getintfield(self.bzs, 'c_avail_out') == 0:
out.prepare_next_chunk()
@@ -603,23 +602,23 @@
Create a new decompressor object. This object may be used to decompress
data sequentially. If you want to decompress data in one shot, use the
decompress() function instead."""
-
+
def __init__(self, space):
self.space = space
self.bzs = lltype.malloc(bz_stream.TO, flavor='raw', zero=True)
self.running = False
self.unused_data = ""
-
+
self._init_bz2decomp()
-
+
def _init_bz2decomp(self):
bzerror = BZ2_bzDecompressInit(self.bzs, 0, 0)
if bzerror != BZ_OK:
_catch_bz2_error(self.space, bzerror)
-
+
self.running = True
-
+
def __del__(self):
BZ2_bzDecompressEnd(self.bzs)
lltype.free(self.bzs, flavor='raw')
@@ -687,7 +686,7 @@
Compress data in one shot. If you want to compress data sequentially,
use an instance of BZ2Compressor instead. The compresslevel parameter, if
given, must be a number between 1 and 9."""
-
+
if compresslevel < 1 or compresslevel > 9:
raise OperationError(space.w_ValueError,
space.wrap("compresslevel must be between 1 and 9"))
@@ -731,7 +730,7 @@
Decompress data in one shot. If you want to decompress data sequentially,
use an instance of BZ2Decompressor instead."""
-
+
in_bufsize = len(data)
if in_bufsize == 0:
return space.wrap("")
diff --git a/pypy/module/bz2/test/test_bz2_file.py b/pypy/module/bz2/test/test_bz2_file.py
--- a/pypy/module/bz2/test/test_bz2_file.py
+++ b/pypy/module/bz2/test/test_bz2_file.py
@@ -133,6 +133,7 @@
bz2f.seek(0)
assert bz2f.tell() == 0
+ del bz2f # delete from this frame, which is captured in the traceback
def test_open_close_del(self):
from bz2 import BZ2File
@@ -246,11 +247,18 @@
assert text_read == self.TEXT
bz2f.close()
+ def test_silently_closes(self):
+ from bz2 import BZ2File
+ self.create_broken_temp_file()
+ BZ2File(self.temppath)
+ # check that no C-level malloc is left behind
+
def test_read_broken_file(self):
from bz2 import BZ2File
self.create_broken_temp_file()
bz2f = BZ2File(self.temppath)
raises(EOFError, bz2f.read)
+ del bz2f # delete from this frame, which is captured in the traceback
def test_subsequent_read_broken_file(self):
from bz2 import BZ2File
@@ -264,6 +272,7 @@
raise Exception("should generate EOFError earlier")
except EOFError:
pass
+ del bz2f # delete from this frame, which is captured in the traceback
def test_read_chunk10(self):
from bz2 import BZ2File
@@ -416,6 +425,7 @@
bz2f.close()
bz2f = BZ2File(self.temppath, 'r')
assert bz2f.read() == self.random_data
+ del bz2f # delete from this frame, which is captured in the traceback
def test_context_manager(self):
from bz2 import BZ2File
diff --git a/pypy/module/cStringIO/interp_stringio.py b/pypy/module/cStringIO/interp_stringio.py
--- a/pypy/module/cStringIO/interp_stringio.py
+++ b/pypy/module/cStringIO/interp_stringio.py
@@ -1,4 +1,3 @@
-import sys
from pypy.interpreter.error import OperationError
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.typedef import TypeDef, GetSetProperty
diff --git a/pypy/module/cmath/interp_cmath.py b/pypy/module/cmath/interp_cmath.py
--- a/pypy/module/cmath/interp_cmath.py
+++ b/pypy/module/cmath/interp_cmath.py
@@ -5,7 +5,7 @@
from pypy.tool.sourcetools import func_with_new_name
from pypy.interpreter.error import OperationError
from pypy.interpreter.gateway import NoneNotWrapped
-from pypy.module.cmath import Module, names_and_docstrings
+from pypy.module.cmath import names_and_docstrings
from pypy.module.cmath.constant import DBL_MIN, CM_SCALE_UP, CM_SCALE_DOWN
from pypy.module.cmath.constant import CM_LARGE_DOUBLE, DBL_MANT_DIG
from pypy.module.cmath.constant import M_LN2, M_LN10
diff --git a/pypy/module/cpyext/cdatetime.py b/pypy/module/cpyext/cdatetime.py
--- a/pypy/module/cpyext/cdatetime.py
+++ b/pypy/module/cpyext/cdatetime.py
@@ -1,8 +1,7 @@
from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.rlib.objectmodel import we_are_translated
-from pypy.module.cpyext.pyobject import PyObject, make_ref, Py_DecRef
-from pypy.module.cpyext.api import (
- cpython_api, CANNOT_FAIL, cpython_struct, PyObjectFields)
+from pypy.module.cpyext.pyobject import PyObject, make_ref
+from pypy.module.cpyext.api import (cpython_api, CANNOT_FAIL, cpython_struct,
+ PyObjectFields)
from pypy.module.cpyext.import_ import PyImport_Import
from pypy.module.cpyext.typeobject import PyTypeObjectPtr
from pypy.interpreter.error import OperationError
diff --git a/pypy/module/cpyext/complexobject.py b/pypy/module/cpyext/complexobject.py
--- a/pypy/module/cpyext/complexobject.py
+++ b/pypy/module/cpyext/complexobject.py
@@ -1,7 +1,6 @@
from pypy.rpython.lltypesystem import lltype, rffi
from pypy.module.cpyext.api import (
cpython_api, cpython_struct, PyObject, build_type_checkers)
-from pypy.module.cpyext.pyerrors import PyErr_BadArgument
from pypy.module.cpyext.floatobject import PyFloat_AsDouble
from pypy.objspace.std.complexobject import W_ComplexObject
from pypy.interpreter.error import OperationError
diff --git a/pypy/module/cpyext/include/patchlevel.h b/pypy/module/cpyext/include/patchlevel.h
--- a/pypy/module/cpyext/include/patchlevel.h
+++ b/pypy/module/cpyext/include/patchlevel.h
@@ -29,7 +29,7 @@
#define PY_VERSION "2.7.1"
/* PyPy version as a string */
-#define PYPY_VERSION "1.5.0"
+#define PYPY_VERSION "1.6.0"
/* Subversion Revision number of this file (not of the repository) */
#define PY_PATCHLEVEL_REVISION "$Revision: 77872 $"
diff --git a/pypy/module/cpyext/sequence.py b/pypy/module/cpyext/sequence.py
--- a/pypy/module/cpyext/sequence.py
+++ b/pypy/module/cpyext/sequence.py
@@ -22,7 +22,7 @@
def PySequence_Check(space, w_obj):
"""Return 1 if the object provides sequence protocol, and 0 otherwise.
This function always succeeds."""
- return int(space.findattr(w_obj, space.wrap("__getitem__")) is not None)
+ return int(space.issequence_w(w_obj))
@cpython_api([PyObject], Py_ssize_t, error=-1)
def PySequence_Size(space, w_obj):
diff --git a/pypy/module/crypt/interp_crypt.py b/pypy/module/crypt/interp_crypt.py
--- a/pypy/module/crypt/interp_crypt.py
+++ b/pypy/module/crypt/interp_crypt.py
@@ -1,6 +1,5 @@
-from pypy.interpreter.error import OperationError
from pypy.interpreter.gateway import unwrap_spec
-from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.rpython.lltypesystem import rffi
from pypy.translator.tool.cbuild import ExternalCompilationInfo
import sys
@@ -22,4 +21,4 @@
if not res:
return space.w_None
str_res = rffi.charp2str(res)
- return space.wrap(str_res)
+ return space.wrap(str_res)
diff --git a/pypy/module/exceptions/interp_exceptions.py b/pypy/module/exceptions/interp_exceptions.py
--- a/pypy/module/exceptions/interp_exceptions.py
+++ b/pypy/module/exceptions/interp_exceptions.py
@@ -73,9 +73,8 @@
"""
from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.typedef import TypeDef, interp_attrproperty_w,\
- GetSetProperty, interp_attrproperty, descr_get_dict, descr_set_dict,\
- descr_del_dict
+from pypy.interpreter.typedef import (TypeDef, GetSetProperty, descr_get_dict,
+ descr_set_dict, descr_del_dict)
from pypy.interpreter.gateway import interp2app
from pypy.interpreter.error import OperationError
from pypy.rlib import rwin32
diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -11,9 +11,8 @@
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.eval import Code
from pypy.interpreter.pycode import PyCode
-from pypy.rlib import streamio, jit, rposix
+from pypy.rlib import streamio, jit
from pypy.rlib.streamio import StreamErrors
-from pypy.rlib.rarithmetic import intmask
from pypy.rlib.objectmodel import we_are_translated, specialize
from pypy.module.sys.version import PYPY_VERSION
diff --git a/pypy/module/imp/interp_imp.py b/pypy/module/imp/interp_imp.py
--- a/pypy/module/imp/interp_imp.py
+++ b/pypy/module/imp/interp_imp.py
@@ -3,9 +3,9 @@
from pypy.rlib import streamio
from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.interpreter.module import Module
-from pypy.interpreter.gateway import NoneNotWrapped, unwrap_spec
+from pypy.interpreter.gateway import unwrap_spec
from pypy.module._file.interp_stream import StreamErrors, wrap_streamerror
-import struct
+
def get_suffixes(space):
w = space.wrap
diff --git a/pypy/module/itertools/interp_itertools.py b/pypy/module/itertools/interp_itertools.py
--- a/pypy/module/itertools/interp_itertools.py
+++ b/pypy/module/itertools/interp_itertools.py
@@ -2,7 +2,6 @@
from pypy.interpreter.error import OperationError
from pypy.interpreter.typedef import TypeDef, make_weakref_descr
from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.rlib.rarithmetic import ovfcheck
class W_Count(Wrappable):
@@ -87,7 +86,7 @@
def __init__(self, space, w_obj, w_times):
self.space = space
self.w_obj = w_obj
-
+
if space.is_w(w_times, space.w_None):
self.counting = False
self.count = 0
@@ -181,7 +180,7 @@
long as the predicate is true.
Equivalent to :
-
+
def takewhile(predicate, iterable):
for x in iterable:
if predicate(x):
@@ -316,7 +315,7 @@
None, return the items that are false.
Equivalent to :
-
+
def ifilterfalse(predicate, iterable):
if predicate is None:
predicate = bool
@@ -570,7 +569,7 @@
yield tuple(args)
else:
yield function(*args)
-
+
""")
@@ -728,9 +727,9 @@
__doc__ = """Make an iterator returning elements from the iterable and
saving a copy of each. When the iterable is exhausted, return
elements from the saved copy. Repeats indefinitely.
-
+
Equivalent to :
-
+
def cycle(iterable):
saved = []
for element in iterable:
@@ -738,7 +737,7 @@
saved.append(element)
while saved:
for element in saved:
- yield element
+ yield element
""")
class W_StarMap(Wrappable):
@@ -778,7 +777,7 @@
def starmap(function, iterable):
iterable = iter(iterable)
while True:
- yield function(*iterable.next())
+ yield function(*iterable.next())
""")
@@ -788,15 +787,15 @@
Note : once tee() has made a split, the original iterable
should not be used anywhere else; otherwise, the iterable could get
advanced without the tee objects being informed.
-
+
Note : this member of the toolkit may require significant auxiliary
storage (depending on how much temporary data needs to be stored).
In general, if one iterator is going to use most or all of the
data before the other iterator, it is faster to use list() instead
of tee()
-
+
Equivalent to :
-
+
def tee(iterable, n=2):
def gen(next, data={}, cnt=[0]):
for i in count():
@@ -888,7 +887,7 @@
self.exhausted = False
self.started = False
# new_group - new group not started yet, next should not skip any items
- self.new_group = True
+ self.new_group = True
self.w_lookahead = self.space.w_None
self.w_key = self.space.w_None
diff --git a/pypy/module/marshal/interp_marshal.py b/pypy/module/marshal/interp_marshal.py
--- a/pypy/module/marshal/interp_marshal.py
+++ b/pypy/module/marshal/interp_marshal.py
@@ -1,10 +1,8 @@
-from pypy.interpreter.baseobjspace import ObjSpace
from pypy.interpreter.error import OperationError
from pypy.rlib.rarithmetic import intmask
from pypy.rlib import rstackovf
from pypy.module._file.interp_file import W_File
-from pypy.module._file.interp_stream import StreamErrors, wrap_streamerror
-import sys
+
Py_MARSHAL_VERSION = 2
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -1,4 +1,4 @@
-from pypy.interpreter.baseobjspace import ObjSpace, W_Root, Wrappable
+from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.typedef import TypeDef, GetSetProperty
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -1,7 +1,7 @@
import math
-from pypy.interpreter.gateway import unwrap_spec
-from pypy.module.micronumpy.interp_numarray import BaseArray, Call1, Call2, Signature, convert_to_array
+from pypy.module.micronumpy.interp_numarray import (Call1, Call2, Signature,
+ convert_to_array)
from pypy.rlib import rfloat
from pypy.tool.sourcetools import func_with_new_name
diff --git a/pypy/module/mmap/interp_mmap.py b/pypy/module/mmap/interp_mmap.py
--- a/pypy/module/mmap/interp_mmap.py
+++ b/pypy/module/mmap/interp_mmap.py
@@ -1,21 +1,16 @@
-from pypy.rpython.tool import rffi_platform
-from pypy.rpython.lltypesystem import rffi, lltype
from pypy.interpreter.error import OperationError, wrap_oserror
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.typedef import TypeDef
from pypy.interpreter.gateway import interp2app, unwrap_spec, NoneNotWrapped
from pypy.rlib import rmmap
from pypy.rlib.rmmap import RValueError, RTypeError, ROverflowError
-import sys
-import os
-import platform
-import stat
+
class W_MMap(Wrappable):
def __init__(self, space, mmap_obj):
self.space = space
self.mmap = mmap_obj
-
+
def close(self):
self.mmap.close()
diff --git a/pypy/module/pypyjit/interp_jit.py b/pypy/module/pypyjit/interp_jit.py
--- a/pypy/module/pypyjit/interp_jit.py
+++ b/pypy/module/pypyjit/interp_jit.py
@@ -15,7 +15,6 @@
from pypy.interpreter.gateway import unwrap_spec
from pypy.interpreter.baseobjspace import ObjSpace, W_Root
from opcode import opmap
-from pypy.rlib.objectmodel import we_are_translated
from pypy.rlib.nonconst import NonConstant
from pypy.jit.metainterp.resoperation import rop
from pypy.module.pypyjit.interp_resop import debug_merge_point_from_boxes
@@ -67,7 +66,7 @@
def on_compile(self, logger, looptoken, operations, type, next_instr,
is_being_profiled, ll_pycode):
from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
-
+
space = self.space
cache = space.fromcache(Cache)
if cache.in_recursion:
@@ -171,7 +170,7 @@
# ____________________________________________________________
#
-# Public interface
+# Public interface
def set_param(space, __args__):
'''Configure the tunable JIT parameters.
@@ -213,7 +212,7 @@
class Cache(object):
in_recursion = False
-
+
def __init__(self, space):
self.w_compile_hook = space.w_None
diff --git a/pypy/module/pypyjit/interp_resop.py b/pypy/module/pypyjit/interp_resop.py
--- a/pypy/module/pypyjit/interp_resop.py
+++ b/pypy/module/pypyjit/interp_resop.py
@@ -1,9 +1,9 @@
from pypy.interpreter.typedef import TypeDef, interp_attrproperty
-from pypy.interpreter.baseobjspace import Wrappable, ObjSpace, W_Root
+from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.gateway import unwrap_spec, interp2app
from pypy.interpreter.pycode import PyCode
-from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.lltypesystem import lltype
from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
from pypy.rpython.lltypesystem.rclass import OBJECT
diff --git a/pypy/module/rctime/interp_time.py b/pypy/module/rctime/interp_time.py
--- a/pypy/module/rctime/interp_time.py
+++ b/pypy/module/rctime/interp_time.py
@@ -6,7 +6,6 @@
from pypy.rlib.rarithmetic import ovfcheck_float_to_int
from pypy.rlib import rposix
from pypy.translator.tool.cbuild import ExternalCompilationInfo
-import math
import os
import sys
import time as pytime
@@ -102,7 +101,7 @@
CLOCKS_PER_SEC = platform.ConstantInteger("CLOCKS_PER_SEC")
clock_t = platform.SimpleType("clock_t", rffi.ULONG)
has_gettimeofday = platform.Has('gettimeofday')
-
+
if _POSIX:
calling_conv = 'c'
CConfig.timeval = platform.Struct("struct timeval",
@@ -235,7 +234,7 @@
_set_module_object(space, "timezone", space.wrap(timezone))
_set_module_object(space, 'daylight', space.wrap(daylight))
- tzname_w = [space.wrap(tzname[0]), space.wrap(tzname[1])]
+ tzname_w = [space.wrap(tzname[0]), space.wrap(tzname[1])]
_set_module_object(space, 'tzname', space.newtuple(tzname_w))
_set_module_object(space, 'altzone', space.wrap(altzone))
@@ -310,7 +309,7 @@
space.wrap((rffi.getintfield(t, 'c_tm_wday') + 6) % 7), # want monday == 0
space.wrap(rffi.getintfield(t, 'c_tm_yday') + 1), # want january, 1 == 1
space.wrap(rffi.getintfield(t, 'c_tm_isdst'))]
-
+
w_struct_time = _get_module_object(space, 'struct_time')
w_time_tuple = space.newtuple(time_tuple)
return space.call_function(w_struct_time, w_time_tuple)
@@ -330,7 +329,7 @@
tup_w = space.fixedview(w_tup)
if len(tup_w) != 9:
- raise operationerrfmt(space.w_TypeError,
+ raise operationerrfmt(space.w_TypeError,
"argument must be sequence of "
"length 9, not %d", len(tup_w))
@@ -359,7 +358,7 @@
w_accept2dyear = _get_module_object(space, "accept2dyear")
accept2dyear = space.int_w(w_accept2dyear)
-
+
if y < 1900:
if not accept2dyear:
raise OperationError(space.w_ValueError,
@@ -392,7 +391,7 @@
Return the current time in seconds since the Epoch.
Fractions of a second may be present if the system clock provides them."""
-
+
secs = pytime.time()
return space.wrap(secs)
@@ -420,7 +419,7 @@
not present, current time as returned by localtime() is used."""
seconds = _get_inttime(space, w_seconds)
-
+
t_ref = lltype.malloc(rffi.TIME_TP.TO, 1, flavor='raw')
t_ref[0] = seconds
p = c_ctime(t_ref)
@@ -444,7 +443,7 @@
if not p:
raise OperationError(space.w_ValueError,
space.wrap("unconvertible time"))
-
+
return space.wrap(rffi.charp2str(p)[:-1]) # get rid of new line
def gmtime(space, w_seconds=None):
@@ -462,7 +461,7 @@
t_ref[0] = seconds
p = c_gmtime(t_ref)
lltype.free(t_ref, flavor='raw')
-
+
if not p:
raise OperationError(space.w_ValueError, space.wrap(_get_error_msg()))
return _tm_to_tuple(space, p)
@@ -479,7 +478,7 @@
t_ref[0] = seconds
p = c_localtime(t_ref)
lltype.free(t_ref, flavor='raw')
-
+
if not p:
raise OperationError(space.w_ValueError, space.wrap(_get_error_msg()))
return _tm_to_tuple(space, p)
@@ -524,7 +523,7 @@
See the library reference manual for formatting codes. When the time tuple
is not present, current time as returned by localtime() is used."""
buf_value = _gettmarg(space, w_tup)
-
+
# Checks added to make sure strftime() does not crash Python by
# indexing blindly into some array for a textual representation
# by some bad index (fixes bug #897625).
diff --git a/pypy/module/select/interp_select.py b/pypy/module/select/interp_select.py
--- a/pypy/module/select/interp_select.py
+++ b/pypy/module/select/interp_select.py
@@ -1,9 +1,7 @@
-import math
from pypy.interpreter.typedef import TypeDef
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.interpreter.error import (
- OperationError, operationerrfmt, wrap_oserror)
+from pypy.interpreter.error import OperationError, wrap_oserror
from pypy.rlib import rpoll
import errno
@@ -122,7 +120,7 @@
w_errortype = space.fromcache(Cache).w_error
raise OperationError(w_errortype, space.newtuple([
space.wrap(s.errno), space.wrap(s.get_msg())]))
-
+
return space.newtuple([
space.newlist([iwtd_d[i] for i in iwtd]),
space.newlist([owtd_d[i] for i in owtd]),
diff --git a/pypy/module/struct/formatiterator.py b/pypy/module/struct/formatiterator.py
--- a/pypy/module/struct/formatiterator.py
+++ b/pypy/module/struct/formatiterator.py
@@ -1,11 +1,10 @@
-
from pypy.interpreter.error import OperationError
from pypy.rlib.objectmodel import specialize
from pypy.rlib.rstruct.error import StructError
from pypy.rlib.rstruct.standardfmttable import PACK_ACCEPTS_BROKEN_INPUT
-from pypy.rlib.rstruct.formatiterator import (FormatIterator,
- CalcSizeFormatIterator)
+from pypy.rlib.rstruct.formatiterator import FormatIterator
+
class PackFormatIterator(FormatIterator):
diff --git a/pypy/module/struct/interp_struct.py b/pypy/module/struct/interp_struct.py
--- a/pypy/module/struct/interp_struct.py
+++ b/pypy/module/struct/interp_struct.py
@@ -1,10 +1,7 @@
from pypy.interpreter.gateway import unwrap_spec
-from pypy.interpreter.error import OperationError
+from pypy.module.struct.formatiterator import PackFormatIterator, UnpackFormatIterator
from pypy.rlib.rstruct.error import StructError
-from pypy.module.struct.formatiterator import CalcSizeFormatIterator
-from pypy.module.struct.formatiterator import PackFormatIterator
-from pypy.module.struct.formatiterator import UnpackFormatIterator
-
+from pypy.rlib.rstruct.formatiterator import CalcSizeFormatIterator
@unwrap_spec(format=str)
def calcsize(space, format):
diff --git a/pypy/module/sys/test/test_sysmodule.py b/pypy/module/sys/test/test_sysmodule.py
--- a/pypy/module/sys/test/test_sysmodule.py
+++ b/pypy/module/sys/test/test_sysmodule.py
@@ -476,7 +476,7 @@
assert isinstance(vi[0], int)
assert isinstance(vi[1], int)
assert isinstance(vi[2], int)
- assert vi[3] in ("alpha", "beta", "candidate", "final")
+ assert vi[3] in ("alpha", "beta", "candidate", "dev", "final")
assert isinstance(vi[4], int)
def test_allattributes(self):
@@ -523,4 +523,4 @@
# If this ever actually becomes a compilation option this test should
# be changed.
- assert sys.float_repr_style == "short"
\ No newline at end of file
+ assert sys.float_repr_style == "short"
diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py
--- a/pypy/module/sys/version.py
+++ b/pypy/module/sys/version.py
@@ -10,7 +10,7 @@
CPYTHON_VERSION = (2, 7, 1, "final", 42) #XXX # sync patchlevel.h
CPYTHON_API_VERSION = 1013 #XXX # sync with include/modsupport.h
-PYPY_VERSION = (1, 5, 0, "alpha", 0) #XXX # sync patchlevel.h
+PYPY_VERSION = (1, 6, 0, "dev", 1) #XXX # sync patchlevel.h
if platform.name == 'msvc':
COMPILER_INFO = 'MSC v.%d 32 bit' % (platform.version * 10 + 600)
diff --git a/pypy/module/thread/ll_thread.py b/pypy/module/thread/ll_thread.py
--- a/pypy/module/thread/ll_thread.py
+++ b/pypy/module/thread/ll_thread.py
@@ -1,9 +1,7 @@
from pypy.rpython.lltypesystem import rffi, lltype, llmemory
-from pypy.rpython.tool import rffi_platform as platform
from pypy.translator.tool.cbuild import ExternalCompilationInfo
-import py, os
-from pypy.rpython.extregistry import ExtRegistryEntry
+import py
from pypy.rlib import jit
from pypy.rlib.debug import ll_assert
from pypy.rlib.objectmodel import we_are_translated
@@ -21,6 +19,7 @@
'RPyThreadAcquireLock', 'RPyThreadReleaseLock',
'RPyThreadYield',
'RPyThreadGetStackSize', 'RPyThreadSetStackSize',
+ 'RPyOpaqueDealloc_ThreadLock',
'RPyThreadAfterFork']
)
@@ -52,6 +51,9 @@
c_thread_lock_init = llexternal('RPyThreadLockInit', [TLOCKP], rffi.INT,
threadsafe=False) # may add in a global list
+c_thread_lock_dealloc = llexternal('RPyOpaqueDealloc_ThreadLock', [TLOCKP],
+ lltype.Void,
+ threadsafe=True)
c_thread_acquirelock = llexternal('RPyThreadAcquireLock', [TLOCKP, rffi.INT],
rffi.INT,
threadsafe=True) # release the GIL
@@ -120,7 +122,7 @@
def __enter__(self):
self.acquire(True)
-
+
def __exit__(self, *args):
self.release()
@@ -156,6 +158,9 @@
return ll_lock
def free_ll_lock(ll_lock):
+ c_thread_acquirelock(ll_lock, 0)
+ c_thread_releaselock(ll_lock)
+ c_thread_lock_dealloc(ll_lock)
lltype.free(ll_lock, flavor='raw', track_allocation=False)
def acquire_NOAUTO(ll_lock, flag):
diff --git a/pypy/module/thread/os_local.py b/pypy/module/thread/os_local.py
--- a/pypy/module/thread/os_local.py
+++ b/pypy/module/thread/os_local.py
@@ -1,9 +1,7 @@
from pypy.module.thread import ll_thread as thread
-from pypy.interpreter.error import OperationError
from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.typedef import TypeDef, interp2app
-from pypy.interpreter.typedef import GetSetProperty, descr_get_dict
-from pypy.interpreter.typedef import descr_set_dict
+from pypy.interpreter.typedef import (TypeDef, interp2app, GetSetProperty,
+ descr_get_dict)
class Local(Wrappable):
diff --git a/pypy/module/thread/os_thread.py b/pypy/module/thread/os_thread.py
--- a/pypy/module/thread/os_thread.py
+++ b/pypy/module/thread/os_thread.py
@@ -6,7 +6,6 @@
from pypy.module.thread.error import wrap_thread_error
from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.interpreter.gateway import unwrap_spec, NoneNotWrapped, Arguments
-from pypy.rlib.objectmodel import free_non_gc_object
# Here are the steps performed to start a new thread:
#
@@ -167,14 +166,14 @@
when the function raises an unhandled exception; a stack trace will be
printed unless the exception is SystemExit."""
setup_threads(space)
- if not space.is_true(space.isinstance(w_args, space.w_tuple)):
- raise OperationError(space.w_TypeError,
- space.wrap("2nd arg must be a tuple"))
- if w_kwargs is not None and not space.is_true(space.isinstance(w_kwargs, space.w_dict)):
- raise OperationError(space.w_TypeError,
- space.wrap("optional 3rd arg must be a dictionary"))
+ if not space.is_true(space.isinstance(w_args, space.w_tuple)):
+ raise OperationError(space.w_TypeError,
+ space.wrap("2nd arg must be a tuple"))
+ if w_kwargs is not None and not space.is_true(space.isinstance(w_kwargs, space.w_dict)):
+ raise OperationError(space.w_TypeError,
+ space.wrap("optional 3rd arg must be a dictionary"))
if not space.is_true(space.callable(w_callable)):
- raise OperationError(space.w_TypeError,
+ raise OperationError(space.w_TypeError,
space.wrap("first arg must be callable"))
args = Arguments.frompacked(space, w_args, w_kwargs)
diff --git a/pypy/module/thread/test/test_import_lock.py b/pypy/module/thread/test/test_import_lock.py
--- a/pypy/module/thread/test/test_import_lock.py
+++ b/pypy/module/thread/test/test_import_lock.py
@@ -66,6 +66,9 @@
def test_lock(self, space, monkeypatch):
from pypy.module.imp.importing import getimportlock, importhook
+ # Force importing the module _file now
+ space.builtin.get('file')
+
# Monkeypatch the import lock and add a counter
importlock = getimportlock(space)
original_acquire = importlock.acquire_lock
diff --git a/pypy/module/unicodedata/generate_unicodedb.py b/pypy/module/unicodedata/generate_unicodedb.py
--- a/pypy/module/unicodedata/generate_unicodedb.py
+++ b/pypy/module/unicodedata/generate_unicodedb.py
@@ -1,7 +1,5 @@
#!/usr/bin/env python
-import pprint
-
MAXUNICODE = 0x10FFFF # the value of sys.maxunicode of wide Python builds
MANDATORY_LINE_BREAKS = ["BK", "CR", "LF", "NL"] # line break categories
@@ -66,16 +64,16 @@
self.upper = int(data[12], 16)
self.lower = None
if data[13]:
- self.lower = int(data[13], 16)
+ self.lower = int(data[13], 16)
self.title = None
if data[14]:
self.title = int(data[14], 16)
-
+
def copy(self):
uc = Unicodechar()
uc.__dict__.update(self.__dict__)
return uc
-
+
def get_compat_decomposition(table, code):
if not table[code].decomposition:
return [code]
@@ -177,13 +175,13 @@
for code in range(len(table)):
if table[code] is None:
table[code] = defaultChar
-
+
extra_numeric = read_unihan(unihan_file)
for code, value in extra_numeric.iteritems():
uc = table[code].copy()
uc.numeric = value
table[code] = uc
-
+
# Compute full decompositions.
for code in range(len(table)):
get_canonical_decomposition(table, code)
@@ -365,7 +363,7 @@
print >> outfile, '%r: %r,' % (code, name)
print >> outfile, '}'
-
+
print >> outfile, '_names_corrected = {'
for name, code in sorted(base_mod._orig_names.iteritems()):
if name not in names:
@@ -389,7 +387,7 @@
print >> outfile, '%r: None,' % name
print >> outfile, '}'
-
+
def writeUnicodedata(version, table, outfile, base):
if base:
print >> outfile, 'import %s as base_mod' % base
@@ -406,7 +404,7 @@
cjk_end = 0x9FBB
write_character_names(outfile, table, base_mod)
-
+
print >> outfile, '''
_cjk_prefix = "CJK UNIFIED IDEOGRAPH-"
_hangul_prefix = 'HANGUL SYLLABLE '
@@ -496,7 +494,7 @@
v_code = vl_code %% len(_hangul_V)
return ("HANGUL SYLLABLE " + _hangul_L[l_code] +
_hangul_V[v_code] + _hangul_T[t_code])
-
+
if not base_mod:
return lookup_charcode(code)
else:
@@ -522,7 +520,7 @@
digit[code] = table[code].digit
if table[code].numeric is not None:
numeric[code] = table[code].numeric
-
+
writeDict(outfile, '_decimal', decimal, base_mod)
writeDict(outfile, '_digit', digit, base_mod)
writeDict(outfile, '_numeric', numeric, base_mod)
@@ -662,11 +660,11 @@
'''
def main():
- import re, sys
+ import sys
from optparse import OptionParser
infile = None
outfile = sys.stdout
-
+
parser = OptionParser('Usage: %prog [options]')
parser.add_option('--base', metavar='FILENAME', help='Base python version (for import)')
parser.add_option('--output', metavar='OUTPUT_MODULE', help='Output module (implied py extension)')
diff --git a/pypy/objspace/std/mapdict.py b/pypy/objspace/std/mapdict.py
--- a/pypy/objspace/std/mapdict.py
+++ b/pypy/objspace/std/mapdict.py
@@ -431,12 +431,17 @@
return None
assert isinstance(lifeline, WeakrefLifeline)
return lifeline
+ getweakref._cannot_really_call_random_things_ = True
def setweakref(self, space, weakreflifeline):
from pypy.module._weakref.interp__weakref import WeakrefLifeline
- assert (isinstance(weakreflifeline, WeakrefLifeline) or
- weakreflifeline is None)
+ assert isinstance(weakreflifeline, WeakrefLifeline)
self._get_mapdict_map().write(self, ("weakref", SPECIAL), weakreflifeline)
+ setweakref._cannot_really_call_random_things_ = True
+
+ def delweakref(self):
+ self._get_mapdict_map().write(self, ("weakref", SPECIAL), None)
+ delweakref._cannot_really_call_random_things_ = True
class ObjectMixin(object):
_mixin_ = True
diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py
--- a/pypy/objspace/std/setobject.py
+++ b/pypy/objspace/std/setobject.py
@@ -36,6 +36,8 @@
return self._lifeline_
def setweakref(self, space, weakreflifeline):
self._lifeline_ = weakreflifeline
+ def delweakref(self):
+ self._lifeline_ = None
class W_SetObject(W_BaseSetObject):
from pypy.objspace.std.settype import set_typedef as typedef
diff --git a/pypy/objspace/std/test/test_mapdict.py b/pypy/objspace/std/test/test_mapdict.py
--- a/pypy/objspace/std/test/test_mapdict.py
+++ b/pypy/objspace/std/test/test_mapdict.py
@@ -171,7 +171,7 @@
obj = c.instantiate()
assert obj.getweakref() is None
obj.setweakref(space, lifeline1)
- obj.setweakref(space, None)
+ obj.delweakref()
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -532,6 +532,8 @@
return self._lifeline_
def setweakref(self, space, weakreflifeline):
self._lifeline_ = weakreflifeline
+ def delweakref(self):
+ self._lifeline_ = None
# ____________________________________________________________
# Initialization of type objects
diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -482,6 +482,13 @@
key[2:])
cache[key] = s_value
+ # add the attribute _dont_reach_me_in_del_ (see pypy.rpython.rclass)
+ try:
+ graph = self.bookkeeper.position_key[0]
+ graph.func._dont_reach_me_in_del_ = True
+ except (TypeError, AttributeError):
+ pass
+
return annmodel.s_None
def annotate_hooks(self, **kwds_s):
diff --git a/pypy/rlib/test/test_jit.py b/pypy/rlib/test/test_jit.py
--- a/pypy/rlib/test/test_jit.py
+++ b/pypy/rlib/test/test_jit.py
@@ -83,6 +83,9 @@
t, rtyper, fngraph = self.gengraph(fn, [int])
+ # added by compute_result_annotation()
+ assert fn._dont_reach_me_in_del_ == True
+
def getargs(func):
for graph in t.graphs:
if getattr(graph, 'func', None) is func:
diff --git a/pypy/rpython/lltypesystem/rclass.py b/pypy/rpython/lltypesystem/rclass.py
--- a/pypy/rpython/lltypesystem/rclass.py
+++ b/pypy/rpython/lltypesystem/rclass.py
@@ -400,6 +400,7 @@
assert len(s_func.descriptions) == 1
funcdesc, = s_func.descriptions
graph = funcdesc.getuniquegraph()
+ self.check_graph_of_del_does_not_call_too_much(graph)
FUNCTYPE = FuncType([Ptr(source_repr.object_type)], Void)
destrptr = functionptr(FUNCTYPE, graph.name,
graph=graph,
diff --git a/pypy/rpython/memory/gc/minimark.py b/pypy/rpython/memory/gc/minimark.py
--- a/pypy/rpython/memory/gc/minimark.py
+++ b/pypy/rpython/memory/gc/minimark.py
@@ -34,6 +34,13 @@
the GC in very small programs. Defaults to 8
times the nursery.
+ PYPY_GC_LOSTCARD If between two minor collections we see more than
+ 'PYPY_GC_LOSTCARD * length' writes to the same array,
+ then give up card marking and use the fast write
+ barrier instead. Defaults to 0.3333 for now.
+ Avoid values lower than 0.125: it is the growth
+ factor of list.append().
+
PYPY_GC_DEBUG Enable extra checks around collections that are
too slow for normal use. Values are 0 (off),
1 (on major collections) or 2 (also on minor
@@ -198,6 +205,9 @@
# larger. A value of 0 disables card marking.
"card_page_indices": 128,
+ # See PYPY_GC_LOSTCARD.
+ "lost_card": 1.0 / 3.0,
+
# Objects whose total size is at least 'large_object' bytes are
# allocated out of the nursery immediately, as old objects. The
# minimal allocated size of the nursery is 2x the following
@@ -214,6 +224,7 @@
major_collection_threshold=2.5,
growth_rate_max=2.5, # for tests
card_page_indices=0,
+ lost_card=0.5,
large_object=8*WORD,
ArenaCollectionClass=None,
**kwds):
@@ -235,6 +246,7 @@
self.card_page_shift = 0
while (1 << self.card_page_shift) < self.card_page_indices:
self.card_page_shift += 1
+ self.lost_card = lost_card
#
# 'large_object' limit how big objects can be in the nursery, so
# it gives a lower bound on the allowed size of the nursery.
@@ -355,6 +367,10 @@
else:
self.max_delta = 0.125 * env.get_total_memory()
#
+ lost_card = env.read_float_from_env('PYPY_GC_LOSTCARD')
+ if lost_card > 0.0:
+ self.lost_card = lost_card
+ #
self.minor_collection() # to empty the nursery
llarena.arena_free(self.nursery)
self.nursery_size = newsize
@@ -649,7 +665,7 @@
#
else:
# Reserve N extra words containing card bits before the object.
- extra_words = self.card_marking_words_for_length(length)
+ extra_words = self.card_marking_words_for_length(length) + 1
cardheadersize = WORD * extra_words
extra_flags = GCFLAG_HAS_CARDS | GCFLAG_TRACK_YOUNG_PTRS
# note that if 'can_make_young', then card marking will only
@@ -675,11 +691,15 @@
raise MemoryError("cannot allocate large object")
#
# Reserve the card mark bits as a list of single bytes
- # (the loop is empty in C).
- i = 0
- while i < cardheadersize:
- llarena.arena_reserve(arena + i, llmemory.sizeof(lltype.Char))
- i += 1
+ # followed by a Signed (the loop is empty in C).
+ if cardheadersize > 0:
+ i = 0
+ while i < cardheadersize - WORD:
+ llarena.arena_reserve(arena + i,
+ llmemory.sizeof(lltype.Char))
+ i += 1
+ llarena.arena_reserve(arena + i,
+ llmemory.sizeof(lltype.Signed))
#
# Reserve the actual object. (This is also a no-op in C).
result = arena + cardheadersize
@@ -903,14 +923,11 @@
length = (obj + offset_to_length).signed[0]
extra_words = self.card_marking_words_for_length(length)
#
- size_gc_header = self.gcheaderbuilder.size_gc_header
- p = llarena.getfakearenaaddress(obj - size_gc_header)
i = extra_words * WORD
while i > 0:
- p -= 1
- ll_assert(p.char[0] == '\x00',
+ i -= 1
+ ll_assert(self.get_card(obj, i).char[0] == '\x00',
"the card marker bits are not cleared")
- i -= 1
# ----------
# Write barrier
@@ -1008,6 +1025,8 @@
self.prebuilt_root_objects.append(addr_array)
return
#
+ self.set_cards_flag(addr_array)
+ #
# 'addr_array' is a raw_malloc'ed array with card markers
# in front. Compute the index of the bit to set:
bitindex = index >> self.card_page_shift
@@ -1025,10 +1044,6 @@
# it seems more important that remember_young_pointer_from_array2()
# does not take 3 arguments).
addr_byte.char[0] = chr(byte | bitmask)
- #
- if objhdr.tid & GCFLAG_CARDS_SET == 0:
- self.objects_with_cards_set.append(addr_array)
- objhdr.tid |= GCFLAG_CARDS_SET
remember_young_pointer_from_array2._dont_inline_ = True
assert self.card_page_indices > 0
@@ -1057,6 +1072,8 @@
if not self.appears_to_be_young(newvalue):
return
#
+ self.set_cards_flag(addr_array)
+ #
# 'addr_array' is a raw_malloc'ed array with card markers
# in front. Compute the index of the bit to set:
bitindex = index >> self.card_page_shift
@@ -1069,10 +1086,6 @@
if byte & bitmask:
return
addr_byte.char[0] = chr(byte | bitmask)
- #
- if objhdr.tid & GCFLAG_CARDS_SET == 0:
- self.objects_with_cards_set.append(addr_array)
- objhdr.tid |= GCFLAG_CARDS_SET
return
#
# Logic for the no-cards case, put here to minimize the number
@@ -1090,11 +1103,36 @@
self.remember_young_pointer_from_array3 = (
remember_young_pointer_from_array3)
- def get_card(self, obj, byteindex):
+ def get_card_counter_addr(self, obj):
size_gc_header = self.gcheaderbuilder.size_gc_header
addr_byte = obj - size_gc_header
- return llarena.getfakearenaaddress(addr_byte) + (~byteindex)
+ return llarena.getfakearenaaddress(addr_byte) - WORD
+ def get_card(self, obj, byteindex):
+ return self.get_card_counter_addr(obj) + (~byteindex)
+
+ def set_cards_flag(self, obj):
+ hdr = self.header(obj)
+ if hdr.tid & GCFLAG_CARDS_SET == 0:
+ #
+ # first time we set a card bit in this object
+ self.header(obj).tid |= GCFLAG_CARDS_SET
+ self.objects_with_cards_set.append(obj)
+ #
+ # initialize the counter with the array length and self.lost_card
+ typeid = self.get_type_id(obj)
+ offset_to_length = self.varsize_offset_to_length(typeid)
+ length = (obj + offset_to_length).signed[0]
+ counter = int(length * self.lost_card)
+ self.get_card_counter_addr(obj).signed[0] = counter
+ else:
+ # decrement the counter and if zero is reached, give up on
+ # card marking (up to the next collection).
+ addr = self.get_card_counter_addr(obj)
+ addr.signed[0] -= 1
+ if addr.signed[0] < 0:
+ self.objects_pointing_to_young.append(obj)
+ hdr.tid &= ~GCFLAG_TRACK_YOUNG_PTRS
def assume_young_pointers(self, addr_struct):
"""Called occasionally by the JIT to mean ``assume that 'addr_struct'
@@ -1167,10 +1205,7 @@
addr_dstbyte.char[0] = chr(ord(addr_dstbyte.char[0]) | byte)
i += 1
#
- dest_hdr = self.header(dest_addr)
- if dest_hdr.tid & GCFLAG_CARDS_SET == 0:
- self.objects_with_cards_set.append(dest_addr)
- dest_hdr.tid |= GCFLAG_CARDS_SET
+ self.set_cards_flag(dest_addr)
# ----------
# Nursery collection
@@ -1264,6 +1299,7 @@
length = (obj + offset_to_length).signed[0]
bytes = self.card_marking_bytes_for_length(length)
p = llarena.getfakearenaaddress(obj - size_gc_header)
+ p -= WORD
#
# If the object doesn't have GCFLAG_TRACK_YOUNG_PTRS, then it
# means that it is in 'objects_pointing_to_young' and
@@ -1602,7 +1638,7 @@
"GCFLAG_HAS_CARDS but not has_gcptr_in_varsize")
offset_to_length = self.varsize_offset_to_length(typeid)
length = (obj + offset_to_length).signed[0]
- extra_words = self.card_marking_words_for_length(length)
+ extra_words = self.card_marking_words_for_length(length) + 1
arena -= extra_words * WORD
allocsize += extra_words * WORD
#
diff --git a/pypy/rpython/memory/gc/test/test_direct.py b/pypy/rpython/memory/gc/test/test_direct.py
--- a/pypy/rpython/memory/gc/test/test_direct.py
+++ b/pypy/rpython/memory/gc/test/test_direct.py
@@ -525,6 +525,7 @@
def test_writebarrier_before_copy(self):
from pypy.rpython.memory.gc import minimark
largeobj_size = self.gc.nonlarge_max + 1
+ self.gc.next_major_collection_threshold = 99999.0
p_src = self.malloc(VAR, largeobj_size)
p_dst = self.malloc(VAR, largeobj_size)
# make them old
@@ -564,6 +565,7 @@
from pypy.rpython.memory.gc import minimark
tid = self.get_type_id(VAR)
largeobj_size = self.gc.nonlarge_max + 1
+ self.gc.next_major_collection_threshold = 99999.0
addr_src = self.gc.external_malloc(tid, largeobj_size)
addr_dst = self.gc.external_malloc(tid, largeobj_size)
hdr_src = self.gc.header(addr_src)
diff --git a/pypy/rpython/rclass.py b/pypy/rpython/rclass.py
--- a/pypy/rpython/rclass.py
+++ b/pypy/rpython/rclass.py
@@ -374,6 +374,43 @@
def can_ll_be_null(self, s_value):
return s_value.can_be_none()
+ def check_graph_of_del_does_not_call_too_much(self, graph):
+ # RPython-level __del__() methods should not do "too much".
+ # In the PyPy Python interpreter, they usually do simple things
+ # like file.__del__() closing the file descriptor; or if they
+ # want to do more like call an app-level __del__() method, they
+ # enqueue the object instead, and the actual call is done later.
+ #
+ # Here, as a quick way to check "not doing too much", we check
+ # that from no RPython-level __del__() method we can reach a
+ # JitDriver.
+ #
+ # XXX wrong complexity, but good enough because the set of
+ # reachable graphs should be small
+ callgraph = self.rtyper.annotator.translator.callgraph.values()
+ seen = {graph: None}
+ while True:
+ oldlength = len(seen)
+ for caller, callee in callgraph:
+ if caller in seen and callee not in seen:
+ func = getattr(callee, 'func', None)
+ if getattr(func, '_dont_reach_me_in_del_', False):
+ lst = [str(callee)]
+ g = caller
+ while g:
+ lst.append(str(g))
+ g = seen.get(g)
+ lst.append('')
+ raise TyperError("the RPython-level __del__() method "
+ "in %r calls:%s" % (
+ graph, '\n\t'.join(lst[::-1])))
+ if getattr(func, '_cannot_really_call_random_things_',
+ False):
+ continue
+ seen[callee] = caller
+ if len(seen) == oldlength:
+ break
+
# ____________________________________________________________
def rtype_new_instance(rtyper, classdef, llops, classcallhop=None):
diff --git a/pypy/rpython/test/test_rclass.py b/pypy/rpython/test/test_rclass.py
--- a/pypy/rpython/test/test_rclass.py
+++ b/pypy/rpython/test/test_rclass.py
@@ -7,6 +7,7 @@
from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
from pypy.rpython.rclass import IR_IMMUTABLE, IR_IMMUTABLE_ARRAY
from pypy.rpython.rclass import IR_QUASIIMMUTABLE, IR_QUASIIMMUTABLE_ARRAY
+from pypy.rpython.error import TyperError
from pypy.objspace.flow.model import summary
class EmptyBase(object):
@@ -1021,7 +1022,25 @@
assert typeOf(destrptra).TO.ARGS[0] != typeOf(destrptrb).TO.ARGS[0]
assert destrptra is not None
assert destrptrb is not None
-
+
+ def test_del_forbidden(self):
+ class A(object):
+ def __del__(self):
+ self.foo()
+ def foo(self):
+ self.bar()
+ def bar(self):
+ pass
+ bar._dont_reach_me_in_del_ = True
+ def f():
+ a = A()
+ a.foo()
+ a.bar()
+ t = TranslationContext()
+ t.buildannotator().build_types(f, [])
+ e = py.test.raises(TyperError, t.buildrtyper().specialize)
+ print e.value
+
def test_instance_repr(self):
from pypy.rlib.objectmodel import current_object_addr_as_int
class FooBar(object):
diff --git a/pypy/rpython/test/test_rstr.py b/pypy/rpython/test/test_rstr.py
--- a/pypy/rpython/test/test_rstr.py
+++ b/pypy/rpython/test/test_rstr.py
@@ -231,7 +231,7 @@
const = self.const
def fn(i):
s = [const(''), const('one'), const('two'), const('o'), const('on'), const('ne'), const('e'), const('twos'), const('foobar'), const('fortytwo')]
- return s[i].startswith('o')
+ return s[i].startswith(const('o'))
for i in range(10):
res = self.interpret(fn, [i])
assert res == fn(i)
@@ -251,7 +251,7 @@
const = self.const
def fn(i):
s = [const(''), const('one'), const('two'), const('o'), const('on'), const('ne'), const('e'), const('twos'), const('foobar'), const('fortytwo')]
- return s[i].endswith('e')
+ return s[i].endswith(const('e'))
for i in range(10):
res = self.interpret(fn, [i])
assert res == fn(i)
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
@@ -89,7 +89,7 @@
while asm[asm_index][0] < op.offset:
asm_index += 1
end_index = asm_index
- while asm[end_index][0] < end:
+ while asm[end_index][0] < end and end_index < len(asm) - 1:
end_index += 1
op.asm = '\n'.join([asm[i][1] for i in range(asm_index, end_index)])
return loop
@@ -337,26 +337,44 @@
addrs = {}
for entry in extract_category(log, 'jit-backend-addr'):
m = re.search('bootstrap ([\da-f]+)', entry)
- name = entry[:entry.find('(') - 1]
- addrs[int(m.group(1), 16)] = name
+ if not m:
+ # a bridge
+ m = re.search('has address ([\da-f]+)', entry)
+ addr = int(m.group(1), 16)
+ entry = entry.lower()
+ m = re.search('guard \d+', entry)
+ name = m.group(0)
+ else:
+ name = entry[:entry.find('(') - 1].lower()
+ addr = int(m.group(1), 16)
+ addrs.setdefault(addr, []).append(name)
dumps = {}
for entry in extract_category(log, 'jit-backend-dump'):
backend, _, dump, _ = entry.split("\n")
_, addr, _, data = re.split(" +", dump)
backend_name = backend.split(" ")[1]
addr = int(addr[1:], 16)
- if addr in addrs:
- dumps[addrs[addr]] = (backend_name, addr, data)
+ if addr in addrs and addrs[addr]:
+ name = addrs[addr].pop(0) # they should come in order
+ dumps[name] = (backend_name, addr, data)
loops = []
for entry in extract_category(log, 'jit-log-opt'):
parser = ParserCls(entry, None, {}, 'lltype', None,
nonstrict=True)
loop = parser.parse()
comm = loop.comment
- name = comm[2:comm.find(':')-1]
+ comm = comm.lower()
+ if comm.startswith('# bridge'):
+ m = re.search('guard \d+', comm)
+ name = m.group(0)
+ else:
+ name = comm[2:comm.find(':')-1]
if name in dumps:
bname, start_ofs, dump = dumps[name]
- parser.postprocess(loop, backend_tp=bname, backend_dump=dump,
- dump_start=start_ofs)
+ loop.force_asm = (lambda dump=dump, start_ofs=start_ofs,
+ bname=bname, loop=loop:
+ parser.postprocess(loop, backend_tp=bname,
+ backend_dump=dump,
+ dump_start=start_ofs))
loops.append(loop)
return log, loops
diff --git a/pypy/tool/jitlogparser/test/logtest2.log b/pypy/tool/jitlogparser/test/logtest2.log
new file mode 100644
--- /dev/null
+++ b/pypy/tool/jitlogparser/test/logtest2.log
@@ -0,0 +1,301 @@
+[1f5e7f69779] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b000 +0 4157415641554154415341524151415057565554535251504889E349C7C340BC920041FFD34889DF4883E4F049C7C350BC920041FFD3488D65D8415F415E415D415C5B5DC3
+[1f5e7f7fe75] jit-backend-dump}
+[1f5e7f84fc4] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b045 +0 4157415641554154415341524151415057565554535251504889E349C7C3F0BB920041FFD34889DF4883E4F049C7C350BC920041FFD3488D65D8415F415E415D415C5B5DC3
+[1f5e7f87ac1] jit-backend-dump}
+[1f5e7f8a0b4] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b08a +0 4157415641554154415341524151415057565554535251504889E34881EC80000000F20F110424F20F114C2408F20F11542410F20F115C2418F20F11642420F20F116C2428F20F11742430F20F117C2438F2440F11442440F2440F114C2448F2440F11542450F2440F115C2458F2440F11642460F2440F116C2468F2440F11742470F2440F117C247849C7C340BC920041FFD34889DF4883E4F049C7C350BC920041FFD3488D65D8415F415E415D415C5B5DC3
+[1f5e7f8da6b] jit-backend-dump}
+[1f5e7f8f4f6] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b13d +0 4157415641554154415341524151415057565554535251504889E34881EC80000000F20F110424F20F114C2408F20F11542410F20F115C2418F20F11642420F20F116C2428F20F11742430F20F117C2438F2440F11442440F2440F114C2448F2440F11542450F2440F115C2458F2440F11642460F2440F116C2468F2440F11742470F2440F117C247849C7C3F0BB920041FFD34889DF4883E4F049C7C350BC920041FFD3488D65D8415F415E415D415C5B5DC3
+[1f5e7f92b83] jit-backend-dump}
+[1f5e7f95b99] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b210 +0 F20F11442410F20F114C2418F20F11542420F20F115C2428F20F11642430F20F116C2438F20F11742440F20F117C2448F2440F11442450F2440F114C2458F2440F11542460F2440F115C2468F2440F11642470F2440F116C2478F2440F11B42480000000F2440F11BC24880000004829C24889D749C7C350A8920041FFE3
+[1f5e7f988d0] jit-backend-dump}
+[1f5e7fa16fb] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b28e +0 F20F10442410F20F104C2418F20F10542420F20F105C2428F20F10642430F20F106C2438F20F10742440F20F107C2448F2440F10442450F2440F104C2458F2440F10542460F2440F105C2468F2440F10642470F2440F106C2478F2440F10B42480000000F2440F10BC2488000000488B1425704F3D01C3
+[1f5e7fa47ac] jit-backend-dump}
+[1f5e7fab3a4] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b305 +0 57565251415041514883EC40F20F110424F20F114C2408F20F11542410F20F115C2418F20F11642420F20F116C2428F20F11742430F20F117C2438488D7D1049C7C340BA520041FFD3488B042550546B024885C0753CF20F107C2438F20F10742430F20F106C2428F20F10642420F20F105C2418F20F10542410F20F104C2408F20F1004244883C44041594158595A5E5FC3488B042558546B0248C7042550546B020000000048C7042558546B02000000004889042590C2540149C7C340BC920041FFD348C7C0020000004883C478C3
+[1f5e7faf1ca] jit-backend-dump}
+[1f5e7fb0813] {jit-backend-counts
+[1f5e7fb0f61] jit-backend-counts}
+[1f5fd38be3e] {jit-backend
+[1f5fe729336] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b3d5 +0 554889E5534154415541564157488DA500000000488B042590C2540148C7042590C254010000000048898570FFFFFF488B042598C2540148C7042598C254010000000048898568FFFFFF488B0425A0C2540148C70425A0C254010000000048898560FFFFFF488B0425A8C2540148C70425A8C254010000000048898558FFFFFF4C8B3C25D04D5B0149BB30B00C0A897F00004D8B334983C60149BB30B00C0A897F00004D89334981FF102700000F8D000000004D89FE4983E7024983FF000F85000000004983C6034C8B3C25A0536B024983EF014C893C25A0536B024983FF000F8C000000004D89F7E99AFFFFFF488B0425A8536B024829E0483B042580DC3C01760D49BB05B3A007897F000041FFD3554889E5534154415541564157488DA550FFFFFF4889BD70FFFFFF4889B568FFFFFF48899560FFFFFF48898D58FFFFFF4D89C7E940FFFFFF49BB00B0A007897F000041FFD34440484C3D030300000049BB00B0A007897F000041FFD34440484C3D39030400000049BB00B0A007897F000041FFD34440484C3907070305000000
+[1f5fe73276a] jit-backend-dump}
+[1f5fe73438f] {jit-backend-addr
+Loop 0 (<code object f, file 'x.py', line 2> #9 LOAD_FAST) has address 7f8907a0b45d to 7f8907a0b4c3 (bootstrap 7f8907a0b3d5)
+[1f5fe7369af] jit-backend-addr}
+[1f5fe737940] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b3e5 +0 50FFFFFF
+[1f5fe74b40e] jit-backend-dump}
+[1f5fe74c63d] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b484 +0 95000000
+[1f5fe74da6a] jit-backend-dump}
+[1f5fe74e438] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b495 +0 9B000000
+[1f5fe74f513] jit-backend-dump}
+[1f5fe74fd2e] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b4b7 +0 91000000
+[1f5fe750d8c] jit-backend-dump}
+[1f5fe75373f] jit-backend}
+[1f5fe755abc] {jit-log-opt-loop
+# Loop 0 : loop with 26 ops
+[p0, p1, p2, p3, i4]
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #9 LOAD_FAST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #12 LOAD_CONST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #15 COMPARE_OP')
++166: i6 = int_lt(i4, 10000)
+guard_true(i6, descr=<Guard3>) [p1, p0, p2, p3, i4]
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #18 POP_JUMP_IF_FALSE')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #21 LOAD_FAST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #24 LOAD_CONST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #27 BINARY_AND')
++179: i8 = int_and(i4, 2)
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #28 POP_JUMP_IF_FALSE')
++186: i9 = int_is_true(i8)
+guard_false(i9, descr=<Guard4>) [p1, p0, p2, p3, i8, i4]
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #44 LOAD_FAST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #47 LOAD_CONST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #50 INPLACE_ADD')
++196: i11 = int_add(i4, 3)
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #51 STORE_FAST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #54 JUMP_ABSOLUTE')
++200: i13 = getfield_raw(40588192, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
++208: i15 = int_sub(i13, 1)
++212: setfield_raw(40588192, i15, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
++220: i17 = int_lt(i15, 0)
+guard_false(i17, descr=<Guard5>) [p1, p0, p2, p3, i11, None, None]
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #9 LOAD_FAST')
++230: jump(p0, p1, p2, p3, i11, descr=<Loop0>)
++238: --end of the loop--
+[1f5fe92b8af] jit-log-opt-loop}
+[1f5fe944ae5] {jit-backend
+[1f5fee20651] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b565 +0 554889E5534154415541564157488DA5000000004C8B3C2590C2540148C7042590C25401000000004C8B342598C2540148C7042598C25401000000004C8B2C25A0C2540148C70425A0C25401000000004C8B2425A8C2540148C70425A8C25401000000004C8B1425D04D5B014C8B0C25B8C2540148C70425B8C25401000000004C8B0425E04D5B01488B3C25E84D5B01488B3425D0C2540148C70425D0C2540100000000488B1C25D8C2540148C70425D8C2540100000000488B1425E0C2540148C70425E0C254010000000049BB38B00C0A897F0000498B0B4883C10149BB38B00C0A897F000049890B4983F8010F85000000004883FE017206813E980700000F85000000004983FA000F850000000049BBA8F0B407897F00004D39DC0F8500000000488B56084881FA102700000F8D000000004989D44883E2024883FA000F85000000004983C403488B1425A0536B024883EA0148891425A0536B024883FA000F8C000000004C89BD70FFFFFF4C89B568FFFFFF4C89AD60FFFFFF4C898D58FFFFFF4D89E749BB5DB4A007897F000041FFE3488B0425A8536B024829E0483B042580DC3C01760D49BB05B3A007897F000041FFD3554889E5534154415541564157488DA550FFFFFF4989FF4989F64989D54989CC4D89C24C8B5D104D89D84C8B5D184C89DF4C8B5D204C89DE4C8B5D284C89DB4C8B5D304C89DAE9CCFEFFFF49BB00B0A007897F000041FFD321383C343029241D180C08030600000049BB00B0A007897F000041FFD3383C18343029240C08030700000049BB00B0A007897F000041FFD329383C3430241808030800000049BB00B0A007897F000041FFD3383C3034241808030900000049BB00B0A007897F000041FFD3383C183424030A00000049BB00B0A007897F000041FFD3383C34241809030B00000049BB00B0A007897F000041FFD3383C34243107030C000000
+[1f5fee2e673] jit-backend-dump}
+[1f5fee2f38d] {jit-backend-addr
+Loop 1 (<code object f, file 'x.py', line 2> #9 LOAD_FAST) has address 7f8907a0b631 to 7f8907a0b6f8 (bootstrap 7f8907a0b565)
+[1f5fee312e3] jit-backend-addr}
+[1f5fee320ed] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b575 +0 50FFFFFF
+[1f5fee3e903] jit-backend-dump}
+[1f5fee3fbff] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b655 +0 0C010000
+[1f5fee41579] jit-backend-dump}
+[1f5fee421af] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b667 +0 17010000
+[1f5fee43835] jit-backend-dump}
+[1f5fee44261] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b671 +0 28010000
+[1f5fee457c1] jit-backend-dump}
+[1f5fee461a5] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b684 +0 2F010000
+[1f5fee475d3] jit-backend-dump}
+[1f5fee47f57] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b695 +0 37010000
+[1f5fee4933d] jit-backend-dump}
+[1f5fee49cd9] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b6a6 +0 3D010000
+[1f5fee4b0ad] jit-backend-dump}
+[1f5fee4ba4f] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b6c8 +0 33010000
+[1f5fee4cf61] jit-backend-dump}
+[1f5fee4dc45] jit-backend}
+[1f5fee4f3a9] {jit-log-opt-loop
+# Loop 1 : entry bridge with 31 ops
+[p0, p1, p2, p3, i4, p5, i6, i7, p8, p9, p10]
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #9 LOAD_FAST')
++234: guard_value(i6, 1, descr=<Guard6>) [i6, p1, p0, p2, p3, i4, p5, i7, p8, p9, p10]
++244: guard_nonnull_class(p8, ConstClass(W_IntObject), descr=<Guard7>) [p1, p0, p8, p2, p3, i4, p5, p9, p10]
++262: guard_value(i4, 0, descr=<Guard8>) [i4, p1, p0, p2, p3, p5, p8, p10]
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #12 LOAD_CONST')
++272: guard_value(p3, ConstPtr(ptr14), descr=<Guard9>) [p1, p0, p3, p2, p5, p8, p10]
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #15 COMPARE_OP')
++291: i15 = getfield_gc_pure(p8, descr=<SignedFieldDescr pypy.objspace.std.intobject.W_IntObject.inst_intval 8>)
++295: i17 = int_lt(i15, 10000)
+guard_true(i17, descr=<Guard10>) [p1, p0, p8, p2, p5]
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #18 POP_JUMP_IF_FALSE')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #21 LOAD_FAST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #24 LOAD_CONST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #27 BINARY_AND')
++308: i19 = int_and(i15, 2)
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #28 POP_JUMP_IF_FALSE')
++315: i20 = int_is_true(i19)
+guard_false(i20, descr=<Guard11>) [p1, p0, p2, p5, p8, i19]
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #44 LOAD_FAST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #47 LOAD_CONST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #50 INPLACE_ADD')
++325: i22 = int_add(i15, 3)
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #51 STORE_FAST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #54 JUMP_ABSOLUTE')
++329: i24 = getfield_raw(40588192, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
++337: i26 = int_sub(i24, 1)
++341: setfield_raw(40588192, i26, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
++349: i28 = int_lt(i26, 0)
+guard_false(i28, descr=<Guard12>) [p1, p0, p2, p5, i22, None]
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #9 LOAD_FAST')
++359: jump(p0, p1, p2, p5, i22, descr=<Loop0>)
++403: --end of the loop--
+[1f60036d952] jit-log-opt-loop}
+[1f600719a74] {jit-backend
+[1f600759dac] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b817 +0 554889E5534154415541564157488DA500000000488B042590C2540148C7042590C254010000000048898570FFFFFF488B042598C2540148C7042598C254010000000048898568FFFFFF488B0425A0C2540148C70425A0C254010000000048898560FFFFFF488B0425A8C2540148C70425A8C254010000000048898558FFFFFF4C8B3C25D04D5B0149BB40B00C0A897F00004D8B334983C60149BB40B00C0A897F00004D89334981FF102700000F8D000000004D89FE4983E7024983FF000F85000000004983C6034C8B3C25A0536B024983EF024C893C25A0536B024983FF000F8C000000004D89F7E99AFFFFFF488B0425A8536B024829E0483B042580DC3C01760D49BB05B3A007897F000041FFD3554889E5534154415541564157488DA550FFFFFF4889BD70FFFFFF4889B568FFFFFF48899560FFFFFF48898D58FFFFFF4D89C7E940FFFFFF49BB00B0A007897F000041FFD34440484C3D030D00000049BB00B0A007897F000041FFD34440484C3D39030E00000049BB00B0A007897F000041FFD34440484C390707030F000000
+[1f60076fd90] jit-backend-dump}
+[1f600770f30] {jit-backend-addr
+Loop 2 (<code object f, file 'x.py', line 2> #9 LOAD_FAST) has address 7f8907a0b89f to 7f8907a0b905 (bootstrap 7f8907a0b817)
+[1f6007730fc] jit-backend-addr}
+[1f600773fde] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b827 +0 50FFFFFF
+[1f600775c76] jit-backend-dump}
+[1f600776a38] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b8c6 +0 95000000
+[1f600778112] jit-backend-dump}
+[1f600778b8c] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b8d7 +0 9B000000
+[1f60077a04a] jit-backend-dump}
+[1f60077aa6a] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b8f9 +0 91000000
+[1f60077bf10] jit-backend-dump}
+[1f60077cc24] jit-backend}
+[1f60077e094] {jit-log-opt-loop
+# Loop 2 : loop with 25 ops
+[p0, p1, p2, p3, i4]
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #12 LOAD_CONST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #15 COMPARE_OP')
++166: i6 = int_lt(i4, 10000)
+guard_true(i6, descr=<Guard13>) [p1, p0, p2, p3, i4]
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #18 POP_JUMP_IF_FALSE')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #21 LOAD_FAST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #24 LOAD_CONST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #27 BINARY_AND')
++179: i8 = int_and(i4, 2)
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #28 POP_JUMP_IF_FALSE')
++186: i9 = int_is_true(i8)
+guard_false(i9, descr=<Guard14>) [p1, p0, p2, p3, i8, i4]
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #44 LOAD_FAST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #47 LOAD_CONST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #50 INPLACE_ADD')
++196: i11 = int_add(i4, 3)
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #51 STORE_FAST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #54 JUMP_ABSOLUTE')
++200: i13 = getfield_raw(40588192, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
++208: i15 = int_sub(i13, 2)
++212: setfield_raw(40588192, i15, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
++220: i17 = int_lt(i15, 0)
+guard_false(i17, descr=<Guard15>) [p1, p0, p2, p3, i11, None, None]
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #9 LOAD_FAST')
++230: jump(p0, p1, p2, p3, i11, descr=<Loop2>)
++238: --end of the loop--
+[1f6007a567c] jit-log-opt-loop}
+[1f600802cd6] {jit-backend
+[1f600862dd8] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b9b7 +0 488DA50000000049BB48B00C0A897F00004D8B3B4983C70149BB48B00C0A897F00004D893B4D89F74983C6010F80000000004C8B3C25A0536B024983EF014C893C25A0536B024983FF000F8C00000000488B0425704F3D01488D5010483B1425784F3D01761A49BB10B2A007897F000041FFD349BB8EB2A007897F000041FFD348C7009807000048891425704F3D014C89700848898550FFFFFF4C8BBD70FFFFFF4C8BB568FFFFFF4C8BAD60FFFFFF49BBA8F0B407897F00004D89DC49C7C2000000004C8B8D58FFFFFF49C7C00100000048C7C709000000488BB550FFFFFF48C7C30000000048C7C20000000049BB31B6A007897F000041FFE349BB00B0A007897F000041FFD3444039484C3D031000000049BB00B0A007897F000041FFD34440484C39070311000000
+[1f60086ba5a] jit-backend-dump}
+[1f60086d36e] {jit-backend-addr
+Bridge out of guard 4 has address 7f8907a0b9b7 to 7f8907a0bab1
+[1f60086ffd2] jit-backend-addr}
+[1f600870dca] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b9ba +0 C0FEFFFF
+[1f60087281c] jit-backend-dump}
+[1f600873506] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b3d5 +0 C8000000
+[1f600874b44] jit-backend-dump}
+[1f6008754d4] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0ba03 +0 C2000000
+[1f600876956] jit-backend-dump}
+[1f600877b1a] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f8907a0b495 +0 1E050000
+[1f600878f4e] jit-backend-dump}
+[1f600884c12] jit-backend}
+[1f60088780a] {jit-log-opt-bridge
+# bridge out of Guard 4 with 16 ops
+[p0, p1, p2, p3, i4, i5]
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #31 LOAD_FAST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #34 LOAD_CONST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #37 INPLACE_ADD')
++37: i7 = int_add_ovf(i5, 1)
+guard_no_overflow(, descr=<Guard16>) [p0, p1, i7, p2, p3, i5]
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #38 STORE_FAST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #41 JUMP_ABSOLUTE')
++50: i9 = getfield_raw(40588192, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
++58: i11 = int_sub(i9, 1)
++62: setfield_raw(40588192, i11, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
++70: i13 = int_lt(i11, 0)
+guard_false(i13, descr=<Guard17>) [p0, p1, p2, p3, i7, None]
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #9 LOAD_FAST')
++80: p16 = new_with_vtable(ConstClass(W_IntObject))
++143: setfield_gc(p16, i7, descr=<SignedFieldDescr pypy.objspace.std.intobject.W_IntObject.inst_intval 8>)
++147: jump(p1, p0, p2, ConstPtr(ptr17), 0, p3, 1, 9, p16, ConstPtr(ptr21), ConstPtr(ptr22), descr=<Loop1>)
++250: --end of the loop--
+[1f6008aa976] jit-log-opt-bridge}
+[1f600912c98] {jit-backend-counts
+0:1982
+1:1985
+2:0
+3:1782
+[1f600916544] jit-backend-counts}
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
@@ -213,4 +213,15 @@
def test_import_log():
_, loops = import_log(str(py.path.local(__file__).join('..',
'logtest.log')))
+ for loop in loops:
+ loop.force_asm()
assert 'jge' in loops[0].operations[3].asm
+
+def test_import_log_2():
+ _, loops = import_log(str(py.path.local(__file__).join('..',
+ 'logtest2.log')))
+ for loop in loops:
+ loop.force_asm()
+ assert 'cmp' in loops[1].operations[1].asm
+ # bridge
+ assert 'jo' in loops[3].operations[3].asm
diff --git a/pypy/translator/c/gcc/trackgcroot.py b/pypy/translator/c/gcc/trackgcroot.py
--- a/pypy/translator/c/gcc/trackgcroot.py
+++ b/pypy/translator/c/gcc/trackgcroot.py
@@ -1824,6 +1824,11 @@
__gccallshapes:
""".replace("__gccallshapes", _globalname("__gccallshapes"))
output.writelines(shapelines)
+ print >> output, """\
+ #if defined(__linux__) && defined(__ELF__)
+ .section .note.GNU-stack,"",%progbits
+ #endif
+ """
def process(self, iterlines, newfile, filename='?'):
parser = PARSERS[format](verbose=self.verbose, shuffle=self.shuffle)
diff --git a/pypy/translator/cli/src/pypylib.cs b/pypy/translator/cli/src/pypylib.cs
--- a/pypy/translator/cli/src/pypylib.cs
+++ b/pypy/translator/cli/src/pypylib.cs
@@ -615,10 +615,28 @@
return s1.StartsWith(s2);
}
+ public static bool ll_startswith_char(string s, char c)
+ {
+ if (s.Length == 0)
+ {
+ return false;
+ }
+ return s[0] == c;
+ }
+
public static bool ll_endswith(string s1, string s2)
{
return s1.EndsWith(s2);
}
+
+ public static bool ll_endswith_char(string s, char c)
+ {
+ if (s.Length == 0)
+ {
+ return false;
+ }
+ return s[s.Length - 1] == c;
+ }
public static int ll_find(string s1, string s2, int start, int stop)
{
diff --git a/pypy/translator/jvm/src/pypy/PyPy.java b/pypy/translator/jvm/src/pypy/PyPy.java
--- a/pypy/translator/jvm/src/pypy/PyPy.java
+++ b/pypy/translator/jvm/src/pypy/PyPy.java
@@ -791,6 +791,20 @@
return str.substring(start,start+cnt);
}
+ public static boolean ll_startswith_char(String str, char c) {
+ if (str.length() == 0) {
+ return false;
+ }
+ return str.charAt(0) == c;
+ }
+
+ public static boolean ll_endswith_char(String str, char c) {
+ if (str.length() == 0) {
+ return false;
+ }
+ return str.charAt(str.length() - 1) == c;
+ }
+
// ----------------------------------------------------------------------
// StringBuffer
More information about the pypy-commit
mailing list