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

Reply via email to