Author: Hakan Ardo <ha...@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)) +@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 -@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 -@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 -@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 -@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 - -@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 - -@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 -@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 - -@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 -@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") -@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) -@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? - -@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')) - -@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) +@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. _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit