Author: Ronan Lamy <ronan.l...@gmail.com> Branch: py3.5 Changeset: r92544:41b2cbb76719 Date: 2017-10-02 01:02 +0200 http://bitbucket.org/pypy/pypy/changeset/41b2cbb76719/
Log: hg merge default diff --git a/pypy/doc/release-v5.9.0.rst b/pypy/doc/release-v5.9.0.rst --- a/pypy/doc/release-v5.9.0.rst +++ b/pypy/doc/release-v5.9.0.rst @@ -10,15 +10,18 @@ This new PyPy2.7 release includes the upstream stdlib version 2.7.13, and PyPy3.5 includes the upstream stdlib version 3.5.3. -NumPy and Pandas now work on PyPy2.7. Issues that appeared as excessive memory +NumPy and Pandas now work on PyPy2.7 (together with Cython 0.27.1). Issues +that appeared as excessive memory use were cleared up and other incompatibilities were resolved. The C-API compatibility layer does slow down code which crosses the python-c interface often, we have ideas on how it could be improved, and still recommend using pure python on PyPy or interfacing via CFFI_. Many other modules based on C-API exentions now work on PyPy as well. -Cython 0.27 (released last week) should support more projects with PyPy, both -on PyPy2.7 and PyPy3.5 beta. +Cython 0.27.1 (released very recently) supports more projects with PyPy, both +on PyPy2.7 and PyPy3.5 beta. Note version **0.27.1** is now the minimum +version that supports this version of PyPy, due to some interactions with +updated C-API interface code. We optimized the JSON parser for recurring string keys, which should decrease memory use to 50% and increase parsing speed by up to 15% for large JSON files diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -4,3 +4,12 @@ .. this is a revision shortly after release-pypy2.7-v5.9.0 .. startrev:899e5245de1e + +.. branch: cpyext-jit + +Differentiate the code to call METH_NOARGS, METH_O and METH_VARARGS in cpyext: +this allows to write specialized code which is much faster than previous +completely generic version. Moreover, let the JIT to look inside the cpyext +module: the net result is that cpyext calls are up to 7x faster. However, this +is true only for very simple situations: in all real life code, we are still +much slower than CPython (more optimizations to come) diff --git a/pypy/module/_cffi_backend/cffi1_module.py b/pypy/module/_cffi_backend/cffi1_module.py --- a/pypy/module/_cffi_backend/cffi1_module.py +++ b/pypy/module/_cffi_backend/cffi1_module.py @@ -1,4 +1,5 @@ from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rlib import jit from pypy.interpreter.error import oefmt from pypy.interpreter.module import Module @@ -15,7 +16,7 @@ INITFUNCPTR = lltype.Ptr(lltype.FuncType([rffi.VOIDPP], lltype.Void)) - +@jit.dont_look_inside def load_cffi1_module(space, name, path, initptr): # This is called from pypy.module.cpyext.api.load_extension_module() from pypy.module._cffi_backend.call_python import get_ll_cffi_call_python diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py --- a/pypy/module/_cffi_backend/ctypeptr.py +++ b/pypy/module/_cffi_backend/ctypeptr.py @@ -158,10 +158,11 @@ class W_CTypePtrBase(W_CTypePtrOrArray): # base class for both pointers and pointers-to-functions - _attrs_ = ['is_void_ptr', 'is_voidchar_ptr'] - _immutable_fields_ = ['is_void_ptr', 'is_voidchar_ptr'] + _attrs_ = ['is_void_ptr', 'is_voidchar_ptr', 'is_onebyte_ptr'] + _immutable_fields_ = ['is_void_ptr', 'is_voidchar_ptr', 'is_onebyte_ptr'] is_void_ptr = False is_voidchar_ptr = False + is_onebyte_ptr = False def convert_to_object(self, cdata): ptrdata = rffi.cast(rffi.CCHARPP, cdata)[0] @@ -181,12 +182,20 @@ if self.is_void_ptr or other.is_void_ptr: pass # cast from or to 'void *' elif self.is_voidchar_ptr or other.is_voidchar_ptr: - space = self.space - msg = ("implicit cast from '%s' to '%s' " - "will be forbidden in the future (check that the types " - "are as you expect; use an explicit ffi.cast() if they " - "are correct)" % (other.name, self.name)) - space.warn(space.newtext(msg), space.w_UserWarning) + # for backward compatibility, accept "char *" as either + # source of target. This is not what C does, though, + # so emit a warning that will eventually turn into an + # error. The warning is turned off if both types are + # pointers to single bytes. + if self.is_onebyte_ptr and other.is_onebyte_ptr: + pass # no warning + else: + space = self.space + msg = ("implicit cast from '%s' to '%s' " + "will be forbidden in the future (check that the types " + "are as you expect; use an explicit ffi.cast() if they " + "are correct)" % (other.name, self.name)) + space.warn(space.newtext(msg), space.w_UserWarning) else: raise self._convert_error("compatible pointer", w_ob) @@ -216,6 +225,7 @@ self.is_void_ptr = isinstance(ctitem, ctypevoid.W_CTypeVoid) self.is_voidchar_ptr = (self.is_void_ptr or isinstance(ctitem, ctypeprim.W_CTypePrimitiveChar)) + self.is_onebyte_ptr = (ctitem.size == 1) W_CTypePtrBase.__init__(self, space, size, extra, 2, ctitem) def newp(self, w_init, allocator): diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -2099,7 +2099,8 @@ if sys.platform.startswith("linux"): BWChar = new_primitive_type("wchar_t") assert sizeof(BWChar) == 4 - assert int(cast(BWChar, -1)) == -1 # signed, on linux + # wchar_t is often signed on Linux, but not always (e.g. on ARM) + assert int(cast(BWChar, -1)) in (-1, 4294967295) def test_char16(): BChar16 = new_primitive_type("char16_t") @@ -3903,9 +3904,11 @@ BCharP = new_pointer_type(new_primitive_type("char")) BIntP = new_pointer_type(new_primitive_type("int")) BVoidP = new_pointer_type(new_void_type()) + BUCharP = new_pointer_type(new_primitive_type("unsigned char")) z1 = cast(BCharP, 0) z2 = cast(BIntP, 0) z3 = cast(BVoidP, 0) + z4 = cast(BUCharP, 0) with warnings.catch_warnings(record=True) as w: newp(new_pointer_type(BIntP), z1) # warn assert len(w) == 1 @@ -3919,6 +3922,12 @@ assert len(w) == 2 newp(new_pointer_type(BIntP), z3) # fine assert len(w) == 2 + newp(new_pointer_type(BCharP), z4) # fine (ignore signedness here) + assert len(w) == 2 + newp(new_pointer_type(BUCharP), z1) # fine (ignore signedness here) + assert len(w) == 2 + newp(new_pointer_type(BUCharP), z3) # fine + assert len(w) == 2 # check that the warnings are associated with lines in this file assert w[1].lineno == w[0].lineno + 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 @@ -453,6 +453,11 @@ if func.__name__ in FUNCTIONS_BY_HEADER[header]: raise ValueError("%s already registered" % func.__name__) func._always_inline_ = 'try' + # + # XXX: should we @jit.dont_look_inside all the @cpython_api functions, + # or we should only disable some of them? + func._jit_look_inside_ = False + # api_function = ApiFunction( argtypes, restype, func, error=_compute_error(error, restype), gil=gil, 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 @@ -1,4 +1,5 @@ from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rlib import jit from pypy.interpreter.baseobjspace import W_Root from pypy.interpreter.error import OperationError, oefmt @@ -42,8 +43,8 @@ from pypy.module.cpyext.object import _dealloc _dealloc(space, py_obj) - class W_PyCFunctionObject(W_Root): + # TODO create a slightly different class depending on the c_ml_flags def __init__(self, space, ml, w_self, w_module=None): self.ml = ml self.name = rffi.charp2str(rffi.cast(rffi.CCHARP, self.ml.c_ml_name)) @@ -56,7 +57,7 @@ w_self = self.w_self flags = rffi.cast(lltype.Signed, self.ml.c_ml_flags) flags &= ~(METH_CLASS | METH_STATIC | METH_COEXIST) - if space.is_true(w_kw) and not flags & METH_KEYWORDS: + if not flags & METH_KEYWORDS and space.is_true(w_kw): raise oefmt(space.w_TypeError, "%s() takes no keyword arguments", self.name) @@ -89,6 +90,20 @@ else: return space.w_None +class W_PyCFunctionObjectNoArgs(W_PyCFunctionObject): + def call(self, space, w_self, w_args, w_kw): + # Call the C function + if w_self is None: + w_self = self.w_self + func = self.ml.c_ml_meth + return generic_cpy_call(space, func, w_self, None) + +class W_PyCFunctionObjectSingleObject(W_PyCFunctionObject): + def call(self, space, w_self, w_o, w_kw): + if w_self is None: + w_self = self.w_self + func = self.ml.c_ml_meth + return generic_cpy_call(space, func, w_self, w_o) class W_PyCMethodObject(W_PyCFunctionObject): w_self = None @@ -208,6 +223,7 @@ (self.method_name, self.w_objclass.name)) +@jit.dont_look_inside def cwrapper_descr_call(space, w_self, __args__): self = space.interp_w(W_PyCWrapperObject, w_self) args_w, kw_w = __args__.unpack() @@ -218,10 +234,22 @@ space.setitem(w_kw, space.newtext(key), w_obj) return self.call(space, w_self, w_args, w_kw) +def cfunction_descr_call_noargs(space, w_self): + # special case for calling with flags METH_NOARGS + self = space.interp_w(W_PyCFunctionObjectNoArgs, w_self) + return self.call(space, None, None, None) +def cfunction_descr_call_single_object(space, w_self, w_o): + # special case for calling with flags METH_O + self = space.interp_w(W_PyCFunctionObjectSingleObject, w_self) + return self.call(space, None, w_o, None) + +@jit.dont_look_inside def cfunction_descr_call(space, w_self, __args__): + # specialize depending on the W_PyCFunctionObject self = space.interp_w(W_PyCFunctionObject, w_self) args_w, kw_w = __args__.unpack() + # XXX __args__.unpack is slow w_args = space.newtuple(args_w) w_kw = space.newdict() for key, w_obj in kw_w.items(): @@ -229,6 +257,7 @@ ret = self.call(space, None, w_args, w_kw) return ret +@jit.dont_look_inside def cclassmethod_descr_call(space, w_self, __args__): self = space.interp_w(W_PyCFunctionObject, w_self) args_w, kw_w = __args__.unpack() @@ -266,6 +295,26 @@ ) W_PyCFunctionObject.typedef.acceptable_as_base_class = False +W_PyCFunctionObjectNoArgs.typedef = TypeDef( + 'builtin_function_or_method', W_PyCFunctionObject.typedef, + __call__ = interp2app(cfunction_descr_call_noargs), + __doc__ = GetSetProperty(W_PyCFunctionObjectNoArgs.get_doc), + __module__ = interp_attrproperty_w('w_module', cls=W_PyCFunctionObjectNoArgs), + __name__ = interp_attrproperty('name', cls=W_PyCFunctionObjectNoArgs, + wrapfn="newtext_or_none"), + ) +W_PyCFunctionObjectNoArgs.typedef.acceptable_as_base_class = False + +W_PyCFunctionObjectSingleObject.typedef = TypeDef( + 'builtin_function_or_method', W_PyCFunctionObject.typedef, + __call__ = interp2app(cfunction_descr_call_single_object), + __doc__ = GetSetProperty(W_PyCFunctionObjectSingleObject.get_doc), + __module__ = interp_attrproperty_w('w_module', cls=W_PyCFunctionObjectSingleObject), + __name__ = interp_attrproperty('name', cls=W_PyCFunctionObjectSingleObject, + wrapfn="newtext_or_none"), + ) +W_PyCFunctionObjectSingleObject.typedef.acceptable_as_base_class = False + W_PyCMethodObject.typedef = TypeDef( 'method_descriptor', __get__ = interp2app(cmethod_descr_get), diff --git a/pypy/module/cpyext/modsupport.py b/pypy/module/cpyext/modsupport.py --- a/pypy/module/cpyext/modsupport.py +++ b/pypy/module/cpyext/modsupport.py @@ -1,13 +1,15 @@ from rpython.rtyper.lltypesystem import rffi, lltype from pypy.module.cpyext.api import ( cpython_api, METH_STATIC, METH_CLASS, METH_COEXIST, CANNOT_FAIL, cts, + METH_NOARGS, METH_O, parse_dir, bootstrap_function, generic_cpy_call, generic_cpy_call_dont_convert_result, slot_function) from pypy.module.cpyext.pyobject import PyObject, as_pyobj, make_typedescr from pypy.interpreter.module import Module from pypy.module.cpyext.methodobject import ( W_PyCFunctionObject, PyCFunction_NewEx, PyDescr_NewMethod, - PyMethodDef, PyDescr_NewClassMethod, PyStaticMethod_New) + PyMethodDef, PyDescr_NewClassMethod, PyStaticMethod_New, + W_PyCFunctionObjectNoArgs, W_PyCFunctionObjectSingleObject) from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall from pypy.module.cpyext.state import State from pypy.interpreter.error import oefmt @@ -165,6 +167,13 @@ "exception", w_mod.w_name) cur_slot = rffi.ptradd(cur_slot, 1) +def _create_pyc_function_object(space, method, w_self, w_name, flags): + flags &= ~(METH_CLASS | METH_STATIC | METH_COEXIST) + if flags == METH_NOARGS: + return W_PyCFunctionObjectNoArgs(space, method, w_self, w_name) + if flags == METH_O: + return W_PyCFunctionObjectSingleObject(space, method, w_self, w_name) + return W_PyCFunctionObject(space, method, w_self, w_name) def convert_method_defs(space, dict_w, methods, w_type, w_self=None, name=None): w_name = space.newtext_or_none(name) @@ -184,7 +193,8 @@ raise oefmt(space.w_ValueError, "module functions cannot set METH_CLASS or " "METH_STATIC") - w_obj = W_PyCFunctionObject(space, method, w_self, w_name) + w_obj = _create_pyc_function_object(space, method, w_self, + w_name, flags) else: if methodname in dict_w and not (flags & METH_COEXIST): continue diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py --- a/pypy/module/cpyext/pyobject.py +++ b/pypy/module/cpyext/pyobject.py @@ -14,7 +14,7 @@ from rpython.rlib.objectmodel import specialize from rpython.rlib.objectmodel import keepalive_until_here from rpython.rtyper.annlowlevel import llhelper -from rpython.rlib import rawrefcount +from rpython.rlib import rawrefcount, jit from rpython.rlib.debug import fatalerror @@ -151,6 +151,7 @@ class InvalidPointerException(Exception): pass +@jit.dont_look_inside def create_ref(space, w_obj, w_userdata=None, immortal=False): """ Allocates a PyObject, and fills its fields with info from the given @@ -190,6 +191,7 @@ w_marker_deallocating = W_Root() +@jit.dont_look_inside def from_ref(space, ref): """ Finds the interpreter object corresponding to the given reference. If the @@ -227,6 +229,7 @@ assert isinstance(w_type, W_TypeObject) return get_typedescr(w_type.layout.typedef).realize(space, ref) +@jit.dont_look_inside def as_pyobj(space, w_obj, w_userdata=None, immortal=False): """ Returns a 'PyObject *' representing the given intepreter object. diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py --- a/pypy/module/cpyext/slotdefs.py +++ b/pypy/module/cpyext/slotdefs.py @@ -420,23 +420,6 @@ from rpython.rlib.nonconst import NonConstant -SLOTS = {} - -@specialize.memo() -def get_slot_tp_function(space, typedef, name): - """Return a description of the slot C function to use for the built-in - type for 'typedef'. The 'name' is the slot name. This is a memo - function that, after translation, returns one of a built-in finite set. - """ - key = (typedef, name) - try: - return SLOTS[key] - except KeyError: - slot_func = build_slot_tp_function(space, typedef, name) - api_func = slot_func.api_func if slot_func else None - SLOTS[key] = api_func - return api_func - def build_slot_tp_function(space, typedef, name): w_type = space.gettypeobject(typedef) diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py --- a/pypy/module/cpyext/typeobject.py +++ b/pypy/module/cpyext/typeobject.py @@ -29,7 +29,7 @@ PyObject, make_ref, from_ref, get_typedescr, make_typedescr, track_reference, Py_DecRef, as_pyobj, incref) from pypy.module.cpyext.slotdefs import ( - slotdefs_for_tp_slots, slotdefs_for_wrappers, get_slot_tp_function, + slotdefs_for_tp_slots, slotdefs_for_wrappers, build_slot_tp_function, llslot) from pypy.module.cpyext.state import State from pypy.module.cpyext.structmember import PyMember_GetOne, PyMember_SetOne @@ -226,7 +226,30 @@ dict_w[name] = w_descr i += 1 +SLOTS = {} +@specialize.memo() +def get_slot_tp_function(space, typedef, name): + """Return a description of the slot C function to use for the built-in + type for 'typedef'. The 'name' is the slot name. This is a memo + function that, after translation, returns one of a built-in finite set. + """ + key = (typedef, name) + try: + return SLOTS[key] + except KeyError: + slot_func = build_slot_tp_function(space, typedef, name) + api_func = slot_func.api_func if slot_func else None + SLOTS[key] = api_func + return api_func + missing_slots={} +def warn_missing_slot(space, method_name, slot_name, w_type): + if not we_are_translated(): + if slot_name not in missing_slots: + missing_slots[slot_name] = w_type.getname(space) + print "missing slot %r/%r, discovered on %r" % ( + method_name, slot_name, w_type.getname(space)) + def update_all_slots(space, w_type, pto): # fill slots in pto # Not very sure about it, but according to @@ -243,13 +266,11 @@ for method_name, slot_name, slot_names, slot_apifunc in slotdefs_for_tp_slots: slot_func_helper = None - if search_dict_w is None: + if typedef is not None: # built-in types: expose as many slots as possible, even # if it happens to come from some parent class - slot_apifunc = None # use get_slot_tp_function + slot_apifunc = get_slot_tp_function(space, typedef, slot_name) else: - # For heaptypes, w_type.layout.typedef will be object's typedef, and - # get_slot_tp_function will fail w_descr = search_dict_w.get(method_name, None) if w_descr: # use the slot_apifunc (userslots) to lookup at runtime @@ -263,59 +284,54 @@ slot_func_helper = getattr(struct, slot_names[1]) if not slot_func_helper: - if typedef is not None: - if slot_apifunc is None: - slot_apifunc = get_slot_tp_function(space, typedef, slot_name) if not slot_apifunc: - if not we_are_translated(): - if slot_name not in missing_slots: - missing_slots[slot_name] = w_type.getname(space) - print "missing slot %r/%r, discovered on %r" % ( - method_name, slot_name, w_type.getname(space)) + warn_missing_slot(space, method_name, slot_name, w_type) continue slot_func_helper = slot_apifunc.get_llhelper(space) + fill_slot(space, pto, w_type, slot_names, slot_func_helper) - # XXX special case wrapper-functions and use a "specific" slot func +@specialize.arg(3) +def fill_slot(space, pto, w_type, slot_names, slot_func_helper): + # XXX special case wrapper-functions and use a "specific" slot func + if len(slot_names) == 1: + if not getattr(pto, slot_names[0]): + setattr(pto, slot_names[0], slot_func_helper) + elif ((w_type is space.w_list or w_type is space.w_tuple) and + slot_names[0] == 'c_tp_as_number'): + # XXX hack - how can we generalize this? The problem is method + # names like __mul__ map to more than one slot, and we have no + # convenient way to indicate which slots CPython have filled + # + # We need at least this special case since Numpy checks that + # (list, tuple) do __not__ fill tp_as_number + pass + elif ((space.issubtype_w(w_type, space.w_bytes) or + space.issubtype_w(w_type, space.w_unicode)) and + slot_names[0] == 'c_tp_as_number'): + # like above but for any str type + pass + else: + assert len(slot_names) == 2 + struct = getattr(pto, slot_names[0]) + if not struct: + #assert not space.config.translating + assert not pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE + if slot_names[0] == 'c_tp_as_number': + STRUCT_TYPE = PyNumberMethods + elif slot_names[0] == 'c_tp_as_sequence': + STRUCT_TYPE = PySequenceMethods + elif slot_names[0] == 'c_tp_as_buffer': + STRUCT_TYPE = PyBufferProcs + elif slot_names[0] == 'c_tp_as_mapping': + STRUCT_TYPE = PyMappingMethods + else: + raise AssertionError( + "Structure not allocated: %s" % (slot_names[0],)) + struct = lltype.malloc(STRUCT_TYPE, flavor='raw', zero=True) + setattr(pto, slot_names[0], struct) - if len(slot_names) == 1: - if not getattr(pto, slot_names[0]): - setattr(pto, slot_names[0], slot_func_helper) - elif ((w_type is space.w_list or w_type is space.w_tuple) and - slot_names[0] == 'c_tp_as_number'): - # XXX hack - how can we generalize this? The problem is method - # names like __mul__ map to more than one slot, and we have no - # convenient way to indicate which slots CPython have filled - # - # We need at least this special case since Numpy checks that - # (list, tuple) do __not__ fill tp_as_number - pass - elif ((space.issubtype_w(w_type, space.w_bytes) or - space.issubtype_w(w_type, space.w_unicode)) and - slot_names[0] == 'c_tp_as_number'): - # like above but for any str type - pass - else: - assert len(slot_names) == 2 - struct = getattr(pto, slot_names[0]) - if not struct: - #assert not space.config.translating - assert not pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE - if slot_names[0] == 'c_tp_as_number': - STRUCT_TYPE = PyNumberMethods - elif slot_names[0] == 'c_tp_as_sequence': - STRUCT_TYPE = PySequenceMethods - elif slot_names[0] == 'c_tp_as_buffer': - STRUCT_TYPE = PyBufferProcs - elif slot_names[0] == 'c_tp_as_mapping': - STRUCT_TYPE = PyMappingMethods - else: - raise AssertionError( - "Structure not allocated: %s" % (slot_names[0],)) - struct = lltype.malloc(STRUCT_TYPE, flavor='raw', zero=True) - setattr(pto, slot_names[0], struct) - - if not getattr(struct, slot_names[1]): - setattr(struct, slot_names[1], slot_func_helper) + if not getattr(struct, slot_names[1]): + setattr(struct, slot_names[1], slot_func_helper) def add_operators(space, dict_w, pto): from pypy.module.cpyext.object import PyObject_HashNotImplemented @@ -395,6 +411,7 @@ ptr = get_new_method_def(space) ptr.c_ml_meth = rffi.cast(PyCFunction, llslot(space, tp_new_wrapper)) +@jit.dont_look_inside def is_tp_new_wrapper(space, ml): return ml.c_ml_meth == rffi.cast(PyCFunction, llslot(space, tp_new_wrapper)) @@ -529,25 +546,18 @@ pto = obj.c_ob_type base = pto this_func_ptr = llslot(space, subtype_dealloc) - w_obj = from_ref(space, rffi.cast(PyObject, base)) # This wrapper is created on a specific type, call it w_A. # We wish to call the dealloc function from one of the base classes of w_A, # the first of which is not this function itself. # w_obj is an instance of w_A or one of its subclasses. So climb up the # inheritance chain until base.c_tp_dealloc is exactly this_func, and then # continue on up until they differ. - #print 'subtype_dealloc, start from', rffi.charp2str(base.c_tp_name) while base.c_tp_dealloc != this_func_ptr: base = base.c_tp_base assert base - #print ' ne move to', rffi.charp2str(base.c_tp_name) - w_obj = from_ref(space, rffi.cast(PyObject, base)) while base.c_tp_dealloc == this_func_ptr: base = base.c_tp_base assert base - #print ' eq move to', rffi.charp2str(base.c_tp_name) - w_obj = from_ref(space, rffi.cast(PyObject, base)) - #print ' end with', rffi.charp2str(base.c_tp_name) dealloc = base.c_tp_dealloc # XXX call tp_del if necessary generic_cpy_call(space, dealloc, obj) @@ -902,7 +912,7 @@ return unrolling_iterable(TABLE) SLOT_TABLE = _parse_typeslots() -def fill_slot(ht, slotnum, ptr): +def fill_ht_slot(ht, slotnum, ptr): for num, membername, slotname, TARGET in SLOT_TABLE: if num == slotnum: setattr(getattr(ht, membername), slotname, rffi.cast(TARGET, ptr)) @@ -977,7 +987,7 @@ # Processed above i += 1 continue - fill_slot(res, slot, slotdef.c_pfunc) + fill_ht_slot(res, slot, slotdef.c_pfunc) # XXX: need to make a copy of the docstring slot, which usually # points to a static string literal i += 1 diff --git a/pypy/module/pypyjit/policy.py b/pypy/module/pypyjit/policy.py --- a/pypy/module/pypyjit/policy.py +++ b/pypy/module/pypyjit/policy.py @@ -14,7 +14,7 @@ return True if '.' in modname: modname, rest = modname.split('.', 1) - if modname in ['unicodedata', 'gc', '_minimal_curses', 'cpyext']: + if modname in ['unicodedata', 'gc', '_minimal_curses']: return False else: rest = '' _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit