[pypy-commit] pypy jit-targets: hg merge default
hakanardo
noreply at buildbot.pypy.org
Mon Nov 7 16:49:45 CET 2011
Author: Hakan Ardo <hakan at debian.org>
Branch: jit-targets
Changeset: r48870:fd948f0bae66
Date: 2011-11-07 16:49 +0100
http://bitbucket.org/pypy/pypy/changeset/fd948f0bae66/
Log: hg merge default
diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -201,7 +201,7 @@
RegrTest('test_difflib.py'),
RegrTest('test_dircache.py', core=True),
RegrTest('test_dis.py'),
- RegrTest('test_distutils.py'),
+ RegrTest('test_distutils.py', skip=True),
RegrTest('test_dl.py', skip=True),
RegrTest('test_doctest.py', usemodules="thread"),
RegrTest('test_doctest2.py'),
diff --git a/lib-python/modified-2.7/ctypes/test/test_simplesubclasses.py b/lib-python/modified-2.7/ctypes/test/test_simplesubclasses.py
--- a/lib-python/modified-2.7/ctypes/test/test_simplesubclasses.py
+++ b/lib-python/modified-2.7/ctypes/test/test_simplesubclasses.py
@@ -1,6 +1,5 @@
import unittest
from ctypes import *
-from ctypes.test import xfail
class MyInt(c_int):
def __cmp__(self, other):
@@ -27,7 +26,6 @@
self.assertEqual(None, cb())
- @xfail
def test_int_callback(self):
args = []
def func(arg):
diff --git a/lib_pypy/_ctypes/structure.py b/lib_pypy/_ctypes/structure.py
--- a/lib_pypy/_ctypes/structure.py
+++ b/lib_pypy/_ctypes/structure.py
@@ -17,7 +17,7 @@
if len(f) == 3:
if (not hasattr(tp, '_type_')
or not isinstance(tp._type_, str)
- or tp._type_ not in "iIhHbBlL"):
+ or tp._type_ not in "iIhHbBlLqQ"):
#XXX: are those all types?
# we just dont get the type name
# in the interp levle thrown TypeError
diff --git a/pypy/jit/metainterp/optimizeopt/__init__.py b/pypy/jit/metainterp/optimizeopt/__init__.py
--- a/pypy/jit/metainterp/optimizeopt/__init__.py
+++ b/pypy/jit/metainterp/optimizeopt/__init__.py
@@ -55,7 +55,7 @@
def optimize_loop_1(metainterp_sd, loop, enable_opts,
- inline_short_preamble=True, retraced=False, bridge=False):
+ inline_short_preamble=True, retraced=False):
"""Optimize loop.operations to remove internal overheadish operations.
"""
@@ -64,7 +64,7 @@
if unroll:
optimize_unroll(metainterp_sd, loop, optimizations)
else:
- optimizer = Optimizer(metainterp_sd, loop, optimizations, bridge)
+ optimizer = Optimizer(metainterp_sd, loop, optimizations)
optimizer.propagate_all_forward()
def optimize_bridge_1(metainterp_sd, bridge, enable_opts,
@@ -76,7 +76,7 @@
except KeyError:
pass
optimize_loop_1(metainterp_sd, bridge, enable_opts,
- inline_short_preamble, retraced, bridge=True)
+ inline_short_preamble, retraced)
if __name__ == '__main__':
print ALL_OPTS_NAMES
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
@@ -234,7 +234,7 @@
or op.is_ovf()):
self.posponedop = op
else:
- self.next_optimization.propagate_forward(op)
+ Optimization.emit_operation(self, op)
def emitting_operation(self, op):
if op.has_no_side_effect():
diff --git a/pypy/jit/metainterp/optimizeopt/intbounds.py b/pypy/jit/metainterp/optimizeopt/intbounds.py
--- a/pypy/jit/metainterp/optimizeopt/intbounds.py
+++ b/pypy/jit/metainterp/optimizeopt/intbounds.py
@@ -6,6 +6,7 @@
IntUpperBound)
from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
from pypy.jit.metainterp.resoperation import rop
+from pypy.jit.metainterp.optimize import InvalidLoop
from pypy.rlib.rarithmetic import LONG_BIT
@@ -13,30 +14,10 @@
"""Keeps track of the bounds placed on integers by guards and remove
redundant guards"""
- def setup(self):
- self.posponedop = None
- self.nextop = None
-
def new(self):
- assert self.posponedop is None
return OptIntBounds()
-
- def flush(self):
- assert self.posponedop is None
-
- def setup(self):
- self.posponedop = None
- self.nextop = None
def propagate_forward(self, op):
- if op.is_ovf():
- self.posponedop = op
- return
- if self.posponedop:
- self.nextop = op
- op = self.posponedop
- self.posponedop = None
-
dispatch_opt(self, op)
def opt_default(self, op):
@@ -179,68 +160,75 @@
r = self.getvalue(op.result)
r.intbound.intersect(b)
+ def optimize_GUARD_NO_OVERFLOW(self, op):
+ lastop = self.last_emitted_operation
+ if lastop is not None:
+ opnum = lastop.getopnum()
+ args = lastop.getarglist()
+ result = lastop.result
+ # If the INT_xxx_OVF was replaced with INT_xxx, then we can kill
+ # the GUARD_NO_OVERFLOW.
+ if (opnum == rop.INT_ADD or
+ opnum == rop.INT_SUB or
+ opnum == rop.INT_MUL):
+ return
+ # Else, synthesize the non overflowing op for optimize_default to
+ # reuse, as well as the reverse op
+ elif opnum == rop.INT_ADD_OVF:
+ self.pure(rop.INT_ADD, args[:], result)
+ self.pure(rop.INT_SUB, [result, args[1]], args[0])
+ self.pure(rop.INT_SUB, [result, args[0]], args[1])
+ elif opnum == rop.INT_SUB_OVF:
+ self.pure(rop.INT_SUB, args[:], result)
+ self.pure(rop.INT_ADD, [result, args[1]], args[0])
+ self.pure(rop.INT_SUB, [args[0], result], args[1])
+ elif opnum == rop.INT_MUL_OVF:
+ self.pure(rop.INT_MUL, args[:], result)
+ self.emit_operation(op)
+
+ def optimize_GUARD_OVERFLOW(self, op):
+ # If INT_xxx_OVF was replaced by INT_xxx, *but* we still see
+ # GUARD_OVERFLOW, then the loop is invalid.
+ lastop = self.last_emitted_operation
+ if lastop is None:
+ raise InvalidLoop
+ opnum = lastop.getopnum()
+ if opnum not in (rop.INT_ADD_OVF, rop.INT_SUB_OVF, rop.INT_MUL_OVF):
+ raise InvalidLoop
+ self.emit_operation(op)
+
def optimize_INT_ADD_OVF(self, op):
v1 = self.getvalue(op.getarg(0))
v2 = self.getvalue(op.getarg(1))
resbound = v1.intbound.add_bound(v2.intbound)
- if resbound.has_lower and resbound.has_upper and \
- self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
- # Transform into INT_ADD and remove guard
+ if resbound.bounded():
+ # Transform into INT_ADD. The following guard will be killed
+ # by optimize_GUARD_NO_OVERFLOW; if we see instead an
+ # optimize_GUARD_OVERFLOW, then InvalidLoop.
op = op.copy_and_change(rop.INT_ADD)
- self.optimize_INT_ADD(op) # emit the op
- else:
- self.emit_operation(op)
- r = self.getvalue(op.result)
- r.intbound.intersect(resbound)
- self.emit_operation(self.nextop)
- if self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
- # Synthesize the non overflowing op for optimize_default to reuse
- self.pure(rop.INT_ADD, op.getarglist()[:], op.result)
- # Synthesize the reverse op for optimize_default to reuse
- self.pure(rop.INT_SUB, [op.result, op.getarg(1)], op.getarg(0))
- self.pure(rop.INT_SUB, [op.result, op.getarg(0)], op.getarg(1))
-
+ self.emit_operation(op) # emit the op
+ r = self.getvalue(op.result)
+ r.intbound.intersect(resbound)
def optimize_INT_SUB_OVF(self, op):
v1 = self.getvalue(op.getarg(0))
v2 = self.getvalue(op.getarg(1))
resbound = v1.intbound.sub_bound(v2.intbound)
- if resbound.has_lower and resbound.has_upper and \
- self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
- # Transform into INT_SUB and remove guard
+ if resbound.bounded():
op = op.copy_and_change(rop.INT_SUB)
- self.optimize_INT_SUB(op) # emit the op
- else:
- self.emit_operation(op)
- r = self.getvalue(op.result)
- r.intbound.intersect(resbound)
- self.emit_operation(self.nextop)
- if self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
- # Synthesize the non overflowing op for optimize_default to reuse
- self.pure(rop.INT_SUB, op.getarglist()[:], op.result)
- # Synthesize the reverse ops for optimize_default to reuse
- self.pure(rop.INT_ADD, [op.result, op.getarg(1)], op.getarg(0))
- self.pure(rop.INT_SUB, [op.getarg(0), op.result], op.getarg(1))
-
+ self.emit_operation(op) # emit the op
+ r = self.getvalue(op.result)
+ r.intbound.intersect(resbound)
def optimize_INT_MUL_OVF(self, op):
v1 = self.getvalue(op.getarg(0))
v2 = self.getvalue(op.getarg(1))
resbound = v1.intbound.mul_bound(v2.intbound)
- if resbound.has_lower and resbound.has_upper and \
- self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
- # Transform into INT_MUL and remove guard
+ if resbound.bounded():
op = op.copy_and_change(rop.INT_MUL)
- self.optimize_INT_MUL(op) # emit the op
- else:
- self.emit_operation(op)
- r = self.getvalue(op.result)
- r.intbound.intersect(resbound)
- self.emit_operation(self.nextop)
- if self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
- # Synthesize the non overflowing op for optimize_default to reuse
- self.pure(rop.INT_MUL, op.getarglist()[:], op.result)
-
+ self.emit_operation(op)
+ r = self.getvalue(op.result)
+ r.intbound.intersect(resbound)
def optimize_INT_LT(self, op):
v1 = self.getvalue(op.getarg(0))
diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -6,7 +6,7 @@
IntLowerBound, MININT, MAXINT
from pypy.jit.metainterp.optimizeopt.util import (make_dispatcher_method,
args_dict)
-from pypy.jit.metainterp.resoperation import rop, ResOperation
+from pypy.jit.metainterp.resoperation import rop, ResOperation, AbstractResOp
from pypy.jit.metainterp.typesystem import llhelper, oohelper
from pypy.tool.pairtype import extendabletype
from pypy.rlib.debug import debug_start, debug_stop, debug_print
@@ -249,6 +249,8 @@
CVAL_ZERO_FLOAT = ConstantValue(Const._new(0.0))
llhelper.CVAL_NULLREF = ConstantValue(llhelper.CONST_NULL)
oohelper.CVAL_NULLREF = ConstantValue(oohelper.CONST_NULL)
+REMOVED = AbstractResOp(None)
+
class Optimization(object):
next_optimization = None
@@ -260,6 +262,7 @@
raise NotImplementedError
def emit_operation(self, op):
+ self.last_emitted_operation = op
self.next_optimization.propagate_forward(op)
# FIXME: Move some of these here?
@@ -327,6 +330,7 @@
def forget_numberings(self, box):
self.optimizer.forget_numberings(box)
+
class Optimizer(Optimization):
def __init__(self, metainterp_sd, loop, optimizations=None):
@@ -340,7 +344,6 @@
self.bool_boxes = {}
self.producer = {}
self.pendingfields = []
- self.exception_might_have_happened = False
self.quasi_immutable_deps = None
self.opaque_pointers = {}
self.replaces_guard = {}
@@ -362,6 +365,7 @@
optimizations[-1].next_optimization = self
for o in optimizations:
o.optimizer = self
+ o.last_emitted_operation = None
o.setup()
else:
optimizations = []
@@ -496,7 +500,6 @@
return CVAL_ZERO
def propagate_all_forward(self, clear=True):
- self.exception_might_have_happened = True
if clear:
self.clear_newoperations()
for op in self.loop.operations:
diff --git a/pypy/jit/metainterp/optimizeopt/pure.py b/pypy/jit/metainterp/optimizeopt/pure.py
--- a/pypy/jit/metainterp/optimizeopt/pure.py
+++ b/pypy/jit/metainterp/optimizeopt/pure.py
@@ -1,4 +1,4 @@
-from pypy.jit.metainterp.optimizeopt.optimizer import Optimization
+from pypy.jit.metainterp.optimizeopt.optimizer import Optimization, REMOVED
from pypy.jit.metainterp.resoperation import rop, ResOperation
from pypy.jit.metainterp.optimizeopt.util import (make_dispatcher_method,
args_dict)
@@ -61,7 +61,10 @@
oldop = self.pure_operations.get(args, None)
if oldop is not None and oldop.getdescr() is op.getdescr():
assert oldop.getopnum() == op.getopnum()
+ # this removes a CALL_PURE that has the same (non-constant)
+ # arguments as a previous CALL_PURE.
self.make_equal_to(op.result, self.getvalue(oldop.result))
+ self.last_emitted_operation = REMOVED
return
else:
self.pure_operations[args] = op
@@ -72,6 +75,13 @@
self.emit_operation(ResOperation(rop.CALL, args, op.result,
op.getdescr()))
+ def optimize_GUARD_NO_EXCEPTION(self, op):
+ if self.last_emitted_operation is REMOVED:
+ # it was a CALL_PURE that was killed; so we also kill the
+ # following GUARD_NO_EXCEPTION
+ return
+ self.emit_operation(op)
+
def flush(self):
assert self.posponedop is None
diff --git a/pypy/jit/metainterp/optimizeopt/rewrite.py b/pypy/jit/metainterp/optimizeopt/rewrite.py
--- a/pypy/jit/metainterp/optimizeopt/rewrite.py
+++ b/pypy/jit/metainterp/optimizeopt/rewrite.py
@@ -294,12 +294,6 @@
raise InvalidLoop
self.optimize_GUARD_CLASS(op)
- def optimize_GUARD_NO_EXCEPTION(self, op):
- if not self.optimizer.exception_might_have_happened:
- return
- self.emit_operation(op)
- self.optimizer.exception_might_have_happened = False
-
def optimize_CALL_LOOPINVARIANT(self, op):
arg = op.getarg(0)
# 'arg' must be a Const, because residual_call in codewriter
@@ -310,6 +304,7 @@
resvalue = self.loop_invariant_results.get(key, None)
if resvalue is not None:
self.make_equal_to(op.result, resvalue)
+ self.last_emitted_operation = REMOVED
return
# change the op to be a normal call, from the backend's point of view
# there is no reason to have a separate operation for this
@@ -444,10 +439,19 @@
except KeyError:
pass
else:
+ # this removes a CALL_PURE with all constant arguments.
self.make_constant(op.result, result)
+ self.last_emitted_operation = REMOVED
return
self.emit_operation(op)
+ def optimize_GUARD_NO_EXCEPTION(self, op):
+ if self.last_emitted_operation is REMOVED:
+ # it was a CALL_PURE or a CALL_LOOPINVARIANT that was killed;
+ # so we also kill the following GUARD_NO_EXCEPTION
+ return
+ self.emit_operation(op)
+
def optimize_INT_FLOORDIV(self, op):
v1 = self.getvalue(op.getarg(0))
v2 = self.getvalue(op.getarg(1))
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
@@ -685,25 +685,60 @@
# ----------
- def test_fold_guard_no_exception(self):
- ops = """
- [i]
- guard_no_exception() []
- i1 = int_add(i, 3)
- guard_no_exception() []
+ def test_keep_guard_no_exception(self):
+ ops = """
+ [i1]
i2 = call(i1, descr=nonwritedescr)
guard_no_exception() [i1, i2]
- guard_no_exception() []
- i3 = call(i2, descr=nonwritedescr)
- jump(i1) # the exception is considered lost when we loop back
- """
- expected = """
- [i]
- i1 = int_add(i, 3)
- i2 = call(i1, descr=nonwritedescr)
+ jump(i2)
+ """
+ self.optimize_loop(ops, ops)
+
+ def test_keep_guard_no_exception_with_call_pure_that_is_not_folded(self):
+ ops = """
+ [i1]
+ i2 = call_pure(123456, i1, descr=nonwritedescr)
guard_no_exception() [i1, i2]
- i3 = call(i2, descr=nonwritedescr)
- jump(i1)
+ jump(i2)
+ """
+ expected = """
+ [i1]
+ i2 = call(123456, i1, descr=nonwritedescr)
+ guard_no_exception() [i1, i2]
+ jump(i2)
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_remove_guard_no_exception_with_call_pure_on_constant_args(self):
+ arg_consts = [ConstInt(i) for i in (123456, 81)]
+ call_pure_results = {tuple(arg_consts): ConstInt(5)}
+ ops = """
+ [i1]
+ i3 = same_as(81)
+ i2 = call_pure(123456, i3, descr=nonwritedescr)
+ guard_no_exception() [i1, i2]
+ jump(i2)
+ """
+ expected = """
+ [i1]
+ jump(5)
+ """
+ self.optimize_loop(ops, expected, call_pure_results)
+
+ def test_remove_guard_no_exception_with_duplicated_call_pure(self):
+ ops = """
+ [i1]
+ i2 = call_pure(123456, i1, descr=nonwritedescr)
+ guard_no_exception() [i1, i2]
+ i3 = call_pure(123456, i1, descr=nonwritedescr)
+ guard_no_exception() [i1, i2, i3]
+ jump(i3)
+ """
+ expected = """
+ [i1]
+ i2 = call(123456, i1, descr=nonwritedescr)
+ guard_no_exception() [i1, i2]
+ jump(i2)
"""
self.optimize_loop(ops, expected)
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -975,17 +975,14 @@
[i]
guard_no_exception() []
i1 = int_add(i, 3)
- guard_no_exception() []
i2 = call(i1, descr=nonwritedescr)
guard_no_exception() [i1, i2]
- guard_no_exception() []
i3 = call(i2, descr=nonwritedescr)
jump(i1) # the exception is considered lost when we loop back
"""
- # note that 'guard_no_exception' at the very start is kept around
- # for bridges, but not for loops
preamble = """
[i]
+ guard_no_exception() [] # occurs at the start of bridges, so keep it
i1 = int_add(i, 3)
i2 = call(i1, descr=nonwritedescr)
guard_no_exception() [i1, i2]
@@ -994,6 +991,7 @@
"""
expected = """
[i]
+ guard_no_exception() [] # occurs at the start of bridges, so keep it
i1 = int_add(i, 3)
i2 = call(i1, descr=nonwritedescr)
guard_no_exception() [i1, i2]
@@ -1002,6 +1000,23 @@
"""
self.optimize_loop(ops, expected, preamble)
+ def test_bug_guard_no_exception(self):
+ ops = """
+ []
+ i0 = call(123, descr=nonwritedescr)
+ p0 = call(0, "xy", descr=s2u_descr) # string -> unicode
+ guard_no_exception() []
+ escape(p0)
+ jump()
+ """
+ expected = """
+ []
+ i0 = call(123, descr=nonwritedescr)
+ escape(u"xy")
+ jump()
+ """
+ self.optimize_loop(ops, expected)
+
# ----------
def test_call_loopinvariant(self):
@@ -6360,12 +6375,15 @@
def test_str2unicode_constant(self):
ops = """
[]
+ escape(1213)
p0 = call(0, "xy", descr=s2u_descr) # string -> unicode
+ guard_no_exception() []
escape(p0)
jump()
"""
expected = """
[]
+ escape(1213)
escape(u"xy")
jump()
"""
@@ -6375,6 +6393,7 @@
ops = """
[p0]
p1 = call(0, p0, descr=s2u_descr) # string -> unicode
+ guard_no_exception() []
escape(p1)
jump(p1)
"""
diff --git a/pypy/jit/metainterp/optimizeopt/vstring.py b/pypy/jit/metainterp/optimizeopt/vstring.py
--- a/pypy/jit/metainterp/optimizeopt/vstring.py
+++ b/pypy/jit/metainterp/optimizeopt/vstring.py
@@ -2,7 +2,8 @@
from pypy.jit.metainterp.history import (BoxInt, Const, ConstInt, ConstPtr,
get_const_ptr_for_string, get_const_ptr_for_unicode, BoxPtr, REF, INT)
from pypy.jit.metainterp.optimizeopt import optimizer, virtualize
-from pypy.jit.metainterp.optimizeopt.optimizer import CONST_0, CONST_1, llhelper
+from pypy.jit.metainterp.optimizeopt.optimizer import CONST_0, CONST_1
+from pypy.jit.metainterp.optimizeopt.optimizer import llhelper, REMOVED
from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
from pypy.jit.metainterp.resoperation import rop, ResOperation
from pypy.rlib.objectmodel import specialize, we_are_translated
@@ -529,6 +530,11 @@
optimize_CALL_PURE = optimize_CALL
+ def optimize_GUARD_NO_EXCEPTION(self, op):
+ if self.last_emitted_operation is REMOVED:
+ return
+ self.emit_operation(op)
+
def opt_call_str_STR2UNICODE(self, op):
# Constant-fold unicode("constant string").
# More generally, supporting non-constant but virtual cases is
@@ -543,6 +549,7 @@
except UnicodeDecodeError:
return False
self.make_constant(op.result, get_const_ptr_for_unicode(u))
+ self.last_emitted_operation = REMOVED
return True
def opt_call_stroruni_STR_CONCAT(self, op, mode):
diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -90,7 +90,10 @@
return op
def __repr__(self):
- return self.repr()
+ try:
+ return self.repr()
+ except NotImplementedError:
+ return object.__repr__(self)
def repr(self, graytext=False):
# RPython-friendly version
diff --git a/pypy/jit/metainterp/test/test_resume.py b/pypy/jit/metainterp/test/test_resume.py
--- a/pypy/jit/metainterp/test/test_resume.py
+++ b/pypy/jit/metainterp/test/test_resume.py
@@ -1135,16 +1135,11 @@
assert ptr2.parent.next == ptr
class CompareableConsts(object):
- def __init__(self):
- self.oldeq = None
-
def __enter__(self):
- assert self.oldeq is None
- self.oldeq = Const.__eq__
Const.__eq__ = Const.same_box
-
+
def __exit__(self, type, value, traceback):
- Const.__eq__ = self.oldeq
+ del Const.__eq__
def test_virtual_adder_make_varray():
b2s, b4s = [BoxPtr(), BoxInt(4)]
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -392,6 +392,7 @@
'Slice': 'space.gettypeobject(W_SliceObject.typedef)',
'StaticMethod': 'space.gettypeobject(StaticMethod.typedef)',
'CFunction': 'space.gettypeobject(cpyext.methodobject.W_PyCFunctionObject.typedef)',
+ 'WrapperDescr': 'space.gettypeobject(cpyext.methodobject.W_PyCMethodObject.typedef)'
}.items():
GLOBALS['Py%s_Type#' % (cpyname, )] = ('PyTypeObject*', pypyexpr)
diff --git a/pypy/module/cpyext/methodobject.py b/pypy/module/cpyext/methodobject.py
--- a/pypy/module/cpyext/methodobject.py
+++ b/pypy/module/cpyext/methodobject.py
@@ -240,6 +240,7 @@
def PyStaticMethod_New(space, w_func):
return space.wrap(StaticMethod(w_func))
+ at cpython_api([PyObject, lltype.Ptr(PyMethodDef)], PyObject)
def PyDescr_NewMethod(space, w_type, method):
return space.wrap(W_PyCMethodObject(space, method, w_type))
diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py
--- a/pypy/module/cpyext/stubs.py
+++ b/pypy/module/cpyext/stubs.py
@@ -586,10 +586,6 @@
def PyDescr_NewMember(space, type, meth):
raise NotImplementedError
- at cpython_api([PyTypeObjectPtr, PyMethodDef], PyObject)
-def PyDescr_NewMethod(space, type, meth):
- raise NotImplementedError
-
@cpython_api([PyTypeObjectPtr, wrapperbase, rffi.VOIDP], PyObject)
def PyDescr_NewWrapper(space, type, wrapper, wrapped):
raise NotImplementedError
@@ -610,14 +606,6 @@
def PyWrapper_New(space, w_d, w_self):
raise NotImplementedError
- at cpython_api([PyObject], PyObject)
-def PyDictProxy_New(space, dict):
- """Return a proxy object for a mapping which enforces read-only behavior.
- This is normally used to create a proxy to prevent modification of the
- dictionary for non-dynamic class types.
- """
- raise NotImplementedError
-
@cpython_api([PyObject, PyObject, rffi.INT_real], rffi.INT_real, error=-1)
def PyDict_Merge(space, a, b, override):
"""Iterate over mapping object b adding key-value pairs to dictionary a.
@@ -2293,15 +2281,6 @@
changes in your code for properly supporting 64-bit systems."""
raise NotImplementedError
- at cpython_api([rffi.CWCHARP, Py_ssize_t, rffi.CCHARP], PyObject)
-def PyUnicode_EncodeUTF8(space, s, size, errors):
- """Encode the Py_UNICODE buffer of the given size using UTF-8 and return a
- Python string object. Return NULL if an exception was raised by the codec.
-
- This function used an int type for size. This might require
- changes in your code for properly supporting 64-bit systems."""
- raise NotImplementedError
-
@cpython_api([rffi.CCHARP, Py_ssize_t, rffi.CCHARP, rffi.INTP], PyObject)
def PyUnicode_DecodeUTF32(space, s, size, errors, byteorder):
"""Decode length bytes from a UTF-32 encoded buffer string and return the
@@ -2481,31 +2460,6 @@
was raised by the codec."""
raise NotImplementedError
- at cpython_api([rffi.CCHARP, Py_ssize_t, rffi.CCHARP], PyObject)
-def PyUnicode_DecodeLatin1(space, s, size, errors):
- """Create a Unicode object by decoding size bytes of the Latin-1 encoded string
- s. Return NULL if an exception was raised by the codec.
-
- This function used an int type for size. This might require
- changes in your code for properly supporting 64-bit systems."""
- raise NotImplementedError
-
- at cpython_api([rffi.CWCHARP, Py_ssize_t, rffi.CCHARP], PyObject)
-def PyUnicode_EncodeLatin1(space, s, size, errors):
- """Encode the Py_UNICODE buffer of the given size using Latin-1 and return
- a Python string object. Return NULL if an exception was raised by the codec.
-
- This function used an int type for size. This might require
- changes in your code for properly supporting 64-bit systems."""
- raise NotImplementedError
-
- at cpython_api([PyObject], PyObject)
-def PyUnicode_AsLatin1String(space, unicode):
- """Encode a Unicode object using Latin-1 and return the result as Python string
- object. Error handling is "strict". Return NULL if an exception was raised
- by the codec."""
- raise NotImplementedError
-
@cpython_api([rffi.CCHARP, Py_ssize_t, PyObject, rffi.CCHARP], PyObject)
def PyUnicode_DecodeCharmap(space, s, size, mapping, errors):
"""Create a Unicode object by decoding size bytes of the encoded string s using
@@ -2564,13 +2518,6 @@
"""
raise NotImplementedError
- at cpython_api([PyObject], PyObject)
-def PyUnicode_AsMBCSString(space, unicode):
- """Encode a Unicode object using MBCS and return the result as Python string
- object. Error handling is "strict". Return NULL if an exception was raised
- by the codec."""
- raise NotImplementedError
-
@cpython_api([PyObject, PyObject], PyObject)
def PyUnicode_Concat(space, left, right):
"""Concat two strings giving a new Unicode string."""
@@ -2912,16 +2859,3 @@
"""Return true if ob is a proxy object.
"""
raise NotImplementedError
-
- at cpython_api([PyObject, PyObject], PyObject)
-def PyWeakref_NewProxy(space, ob, callback):
- """Return a weak reference proxy object for the object ob. This will always
- return a new reference, but is not guaranteed to create a new object; an
- existing proxy object may be returned. The second parameter, callback, can
- be a callable object that receives notification when ob is garbage
- collected; it should accept a single parameter, which will be the weak
- reference object itself. callback may also be None or NULL. If ob
- is not a weakly-referencable object, or if callback is not callable,
- None, or NULL, this will return NULL and raise TypeError.
- """
- raise NotImplementedError
diff --git a/pypy/module/cpyext/test/test_methodobject.py b/pypy/module/cpyext/test/test_methodobject.py
--- a/pypy/module/cpyext/test/test_methodobject.py
+++ b/pypy/module/cpyext/test/test_methodobject.py
@@ -79,7 +79,7 @@
raises(TypeError, mod.isSameFunction, 1)
class TestPyCMethodObject(BaseApiTest):
- def test_repr(self, space):
+ def test_repr(self, space, api):
"""
W_PyCMethodObject has a repr string which describes it as a method
and gives its name and the name of its class.
@@ -94,7 +94,7 @@
ml.c_ml_meth = rffi.cast(PyCFunction_typedef,
c_func.get_llhelper(space))
- method = PyDescr_NewMethod(space, space.w_str, ml)
+ method = api.PyDescr_NewMethod(space.w_str, ml)
assert repr(method).startswith(
"<built-in method 'func' of 'str' object ")
diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test/test_unicodeobject.py
--- a/pypy/module/cpyext/test/test_unicodeobject.py
+++ b/pypy/module/cpyext/test/test_unicodeobject.py
@@ -188,6 +188,12 @@
assert space.unwrap(w_u) == 'sp'
rffi.free_charp(u)
+ def test_encode_utf8(self, space, api):
+ u = rffi.unicode2wcharp(u'sp�m')
+ w_s = api.PyUnicode_EncodeUTF8(u, 4, None)
+ assert space.unwrap(w_s) == u'sp�m'.encode('utf-8')
+ rffi.free_wcharp(u)
+
def test_IS(self, space, api):
for char in [0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x85, 0xa0, 0x1680, 0x2000, 0x2001, 0x2002,
@@ -385,6 +391,24 @@
data, len(u), lltype.nullptr(rffi.CCHARP.TO))
rffi.free_wcharp(data)
+ def test_latin1(self, space, api):
+ s = 'abcdefg'
+ data = rffi.str2charp(s)
+ w_u = api.PyUnicode_DecodeLatin1(data, len(s), lltype.nullptr(rffi.CCHARP.TO))
+ assert space.eq_w(w_u, space.wrap(u"abcdefg"))
+ rffi.free_charp(data)
+
+ uni = u'abcdefg'
+ data = rffi.unicode2wcharp(uni)
+ w_s = api.PyUnicode_EncodeLatin1(data, len(uni), lltype.nullptr(rffi.CCHARP.TO))
+ assert space.eq_w(space.wrap("abcdefg"), w_s)
+ rffi.free_wcharp(data)
+
+ ustr = "abcdef"
+ w_ustr = space.wrap(ustr.decode("ascii"))
+ result = api.PyUnicode_AsLatin1String(w_ustr)
+ assert space.eq_w(space.wrap(ustr), result)
+
def test_format(self, space, api):
w_format = space.wrap(u'hi %s')
w_args = space.wrap((u'test',))
diff --git a/pypy/module/cpyext/test/test_weakref.py b/pypy/module/cpyext/test/test_weakref.py
--- a/pypy/module/cpyext/test/test_weakref.py
+++ b/pypy/module/cpyext/test/test_weakref.py
@@ -15,6 +15,12 @@
assert api.PyErr_Occurred() is space.w_TypeError
api.PyErr_Clear()
+ def test_proxy(self, space, api):
+ w_obj = space.w_Warning # some weakrefable object
+ w_proxy = api.PyWeakref_NewProxy(w_obj, None)
+ assert space.unwrap(space.str(w_proxy)) == "<type 'exceptions.Warning'>"
+ assert space.unwrap(space.repr(w_proxy)).startswith('<weak')
+
def test_weakref_lockobject(self, space, api):
# some new weakrefable object
w_obj = space.call_function(space.w_type, space.wrap("newtype"),
diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -14,6 +14,7 @@
from pypy.module.sys.interp_encoding import setdefaultencoding
from pypy.objspace.std import unicodeobject, unicodetype
from pypy.rlib import runicode
+from pypy.tool.sourcetools import func_renamer
import sys
## See comment in stringobject.py.
@@ -417,26 +418,49 @@
ref[0] = rffi.cast(PyObject, py_newuni)
return 0
- at cpython_api([PyObject], PyObject)
-def PyUnicode_AsUTF8String(space, w_unicode):
- """Encode a Unicode object using UTF-8 and return the result as Python string
- object. Error handling is "strict". Return NULL if an exception was raised
- by the codec."""
- if not PyUnicode_Check(space, w_unicode):
- PyErr_BadArgument(space)
- return unicodetype.encode_object(space, w_unicode, "utf-8", "strict")
+def make_conversion_functions(suffix, encoding):
+ @cpython_api([PyObject], PyObject)
+ @func_renamer('PyUnicode_As%sString' % suffix)
+ def PyUnicode_AsXXXString(space, w_unicode):
+ """Encode a Unicode object and return the result as Python
+ string object. Error handling is "strict". Return NULL if an
+ exception was raised by the codec."""
+ if not PyUnicode_Check(space, w_unicode):
+ PyErr_BadArgument(space)
+ return unicodetype.encode_object(space, w_unicode, encoding, "strict")
- at cpython_api([CONST_STRING, Py_ssize_t, CONST_STRING], PyObject)
-def PyUnicode_DecodeUTF8(space, s, size, errors):
- """Create a Unicode object by decoding size bytes of the UTF-8 encoded string
- s. Return NULL if an exception was raised by the codec.
- """
- w_str = space.wrap(rffi.charpsize2str(s, size))
- if errors:
- w_errors = space.wrap(rffi.charp2str(errors))
- else:
- w_errors = space.w_None
- return space.call_method(w_str, 'decode', space.wrap("utf-8"), w_errors)
+ @cpython_api([CONST_STRING, Py_ssize_t, CONST_STRING], PyObject)
+ @func_renamer('PyUnicode_Decode%s' % suffix)
+ def PyUnicode_DecodeXXX(space, s, size, errors):
+ """Create a Unicode object by decoding size bytes of the
+ encoded string s. Return NULL if an exception was raised by
+ the codec.
+ """
+ w_s = space.wrap(rffi.charpsize2str(s, size))
+ if errors:
+ w_errors = space.wrap(rffi.charp2str(errors))
+ else:
+ w_errors = space.w_None
+ return space.call_method(w_s, 'decode', space.wrap(encoding), w_errors)
+
+ @cpython_api([CONST_WSTRING, Py_ssize_t, CONST_STRING], PyObject)
+ @func_renamer('PyUnicode_Encode%s' % suffix)
+ def PyUnicode_EncodeXXX(space, s, size, errors):
+ """Encode the Py_UNICODE buffer of the given size and return a
+ Python string object. Return NULL if an exception was raised
+ by the codec."""
+ w_u = space.wrap(rffi.wcharpsize2unicode(s, size))
+ if errors:
+ w_errors = space.wrap(rffi.charp2str(errors))
+ else:
+ w_errors = space.w_None
+ return space.call_method(w_u, 'encode', space.wrap(encoding), w_errors)
+
+make_conversion_functions('UTF8', 'utf-8')
+make_conversion_functions('ASCII', 'ascii')
+make_conversion_functions('Latin1', 'latin-1')
+if sys.platform == 'win32':
+ make_conversion_functions('MBCS', 'mbcs')
@cpython_api([rffi.CCHARP, Py_ssize_t, rffi.CCHARP, rffi.INTP], PyObject)
def PyUnicode_DecodeUTF16(space, s, size, llerrors, pbyteorder):
@@ -493,56 +517,6 @@
return space.wrap(result)
- at cpython_api([PyObject], PyObject)
-def PyUnicode_AsASCIIString(space, w_unicode):
- """Encode a Unicode object using ASCII and return the result as Python string
- object. Error handling is "strict". Return NULL if an exception was raised
- by the codec."""
- return space.call_method(w_unicode, 'encode', space.wrap('ascii')) #space.w_None for errors?
-
- at cpython_api([rffi.CCHARP, Py_ssize_t, rffi.CCHARP], PyObject)
-def PyUnicode_DecodeASCII(space, s, size, errors):
- """Create a Unicode object by decoding size bytes of the ASCII encoded string
- s. Return NULL if an exception was raised by the codec."""
- w_s = space.wrap(rffi.charpsize2str(s, size))
- return space.call_method(w_s, 'decode', space.wrap('ascii'))
-
- at cpython_api([rffi.CWCHARP, Py_ssize_t, rffi.CCHARP], PyObject)
-def PyUnicode_EncodeASCII(space, s, size, errors):
- """Encode the Py_UNICODE buffer of the given size using ASCII and return a
- Python string object. Return NULL if an exception was raised by the codec.
- """
-
- w_s = space.wrap(rffi.wcharpsize2unicode(s, size))
- return space.call_method(w_s, 'encode', space.wrap('ascii'))
-
-if sys.platform == 'win32':
- @cpython_api([CONST_WSTRING, Py_ssize_t, CONST_STRING], PyObject)
- def PyUnicode_EncodeMBCS(space, wchar_p, length, errors):
- """Encode the Py_UNICODE buffer of the given size using MBCS and return a
- Python string object. Return NULL if an exception was raised by the codec.
- """
- w_unicode = space.wrap(rffi.wcharpsize2unicode(wchar_p, length))
- if errors:
- w_errors = space.wrap(rffi.charp2str(errors))
- else:
- w_errors = space.w_None
- return space.call_method(w_unicode, "encode",
- space.wrap("mbcs"), w_errors)
-
- @cpython_api([CONST_STRING, Py_ssize_t, CONST_STRING], PyObject)
- def PyUnicode_DecodeMBCS(space, s, size, errors):
- """Create a Unicode object by decoding size bytes of the MBCS encoded string s.
- Return NULL if an exception was raised by the codec.
- """
- w_str = space.wrap(rffi.charpsize2str(s, size))
- w_encoding = space.wrap("mbcs")
- if errors:
- w_errors = space.wrap(rffi.charp2str(errors))
- else:
- w_errors = space.w_None
- return space.call_method(w_str, 'decode', w_encoding, w_errors)
-
@cpython_api([PyObject, PyObject], rffi.INT_real, error=-2)
def PyUnicode_Compare(space, w_left, w_right):
"""Compare two strings and return -1, 0, 1 for less than, equal, and greater
diff --git a/pypy/module/cpyext/weakrefobject.py b/pypy/module/cpyext/weakrefobject.py
--- a/pypy/module/cpyext/weakrefobject.py
+++ b/pypy/module/cpyext/weakrefobject.py
@@ -1,6 +1,6 @@
from pypy.module.cpyext.api import cpython_api
from pypy.module.cpyext.pyobject import PyObject, borrow_from
-from pypy.module._weakref.interp__weakref import W_Weakref
+from pypy.module._weakref.interp__weakref import W_Weakref, proxy
@cpython_api([PyObject, PyObject], PyObject)
def PyWeakref_NewRef(space, w_obj, w_callback):
@@ -16,6 +16,20 @@
w_weakref = space.gettypeobject(W_Weakref.typedef)
return space.call_function(w_weakref, w_obj, w_callback)
+ at cpython_api([PyObject, PyObject], PyObject)
+def PyWeakref_NewProxy(space, w_obj, w_callback):
+ """Return a weak reference proxy object for the object *ob*. This will
+ alwas return a new reference, but is not guaranteed to create a new
+ object; an existing proxy object may be returned. The second parameter,
+ *callback*, can be a callable object that receives notification when *ob*
+ is garbage collected; it should accept a single parameter, which will be
+ the weak reference object itself. *callback* may also be ``None`` or
+ *NULL*. If *ob* is not a weakly-referencable object, or if *callback* is
+ not callable, ``None``, or *NULL*, this will return *NULL* and raise
+ :exc:`TypeError`.
+ """
+ return proxy(space, w_obj, w_callback)
+
@cpython_api([PyObject], PyObject)
def PyWeakref_GetObject(space, w_ref):
"""Return the referenced object from a weak reference. If the referent is
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
@@ -201,6 +201,9 @@
def descr_get_shape(self, space):
return space.newtuple([self.descr_len(space)])
+ def descr_get_size(self, space):
+ return space.wrap(self.find_size())
+
def descr_copy(self, space):
return space.call_function(space.gettypefor(BaseArray), self, self.find_dtype())
@@ -607,6 +610,7 @@
dtype = GetSetProperty(BaseArray.descr_get_dtype),
shape = GetSetProperty(BaseArray.descr_get_shape),
+ size = GetSetProperty(BaseArray.descr_get_size),
mean = interp2app(BaseArray.descr_mean),
sum = interp2app(BaseArray.descr_sum),
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -17,6 +17,14 @@
a[13] = 5.3
assert a[13] == 5.3
+ def test_size(self):
+ from numpy import array
+ # XXX fixed on multidim branch
+ #assert array(3).size == 1
+ a = array([1, 2, 3])
+ assert a.size == 3
+ assert (a + a).size == 3
+
def test_empty(self):
"""
Test that empty() works.
More information about the pypy-commit
mailing list