[pypy-commit] pypy default: Revert the changes done to cpyext which broke it. Too bad for the "nicer"

arigo noreply at buildbot.pypy.org
Fri May 31 15:09:46 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r64677:911bc036c3f2
Date: 2013-05-31 15:13 +0200
http://bitbucket.org/pypy/pypy/changeset/911bc036c3f2/

Log:	Revert the changes done to cpyext which broke it. Too bad for the
	"nicer" version, but to choose, I prefer a working cpyext rather
	than having to look at what's wrong forever.

diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -32,11 +32,10 @@
      "rctime" , "select", "zipimport", "_lsprof",
      "crypt", "signal", "_rawffi", "termios", "zlib", "bz2",
      "struct", "_hashlib", "_md5", "_sha", "_minimal_curses", "cStringIO",
-     "thread", "itertools", "pyexpat", "_ssl", "array",
+     "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array",
      "binascii", "_multiprocessing", '_warnings',
      "_collections", "_multibytecodec", "micronumpy", "_ffi",
-     "_continuation", "_cffi_backend", "_csv"] # "cpyext", "cppyy"]
-# disabled until problems are fixed
+     "_continuation", "_cffi_backend", "_csv", "cppyy"]
 ))
 
 translation_modules = default_modules.copy()
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
@@ -26,7 +26,7 @@
 from pypy.module.__builtin__.descriptor import W_Property
 from pypy.module.__builtin__.interp_classobj import W_ClassObject
 from pypy.module.__builtin__.interp_memoryview import W_MemoryView
-from rpython.rlib.entrypoint import entrypoint
+from rpython.rlib.entrypoint import entrypoint_lowlevel
 from rpython.rlib.rposix import is_valid_fd, validate_fd
 from rpython.rlib.unroll import unrolling_iterable
 from rpython.rlib.objectmodel import specialize
@@ -544,38 +544,37 @@
 def make_wrapper(space, callable):
     "NOT_RPYTHON"
     names = callable.api_func.argnames
-    argtypes = callable.api_func.argtypes
-    is_wrapped_list = [name.startswith("w_") for name in names]
+    argtypes_enum_ui = unrolling_iterable(enumerate(zip(callable.api_func.argtypes,
+        [name.startswith("w_") for name in names])))
     fatal_value = callable.api_func.restype._defl()
 
-    lines = []
-    for i, (argtype, is_wrapped) in enumerate(zip(argtypes, is_wrapped_list)):
-        if is_PyObject(argtype) and is_wrapped:
-            new_lines = [
-                'if %(arg)s:',
-                '    %(arg)s = from_ref(space, rffi.cast(PyObject, %(arg)s))',
-                'else:',
-                '    %(arg)s = None',
-            ]
-            for j in range(len(new_lines)):
-                new_lines[j] = new_lines[j] % {'arg': 'arg%d' % i}
-            lines += new_lines
-    middle = '\n            '.join(lines)
-    arg_spec = ", ".join(["arg%d" % i for i in range(len(argtypes))])
-
-    source = py.code.Source("""
-    def wrapper(%(args)s):
+    @specialize.ll()
+    def wrapper(*args):
         from pypy.module.cpyext.pyobject import make_ref, from_ref
         from pypy.module.cpyext.pyobject import Reference
+        # we hope that malloc removal removes the newtuple() that is
+        # inserted exactly here by the varargs specializer
+        rffi.stackcounter.stacks_counter += 1
+        llop.gc_stack_bottom(lltype.Void)   # marker for trackgcroot.py
         retval = fatal_value
         boxed_args = ()
         try:
             if not we_are_translated() and DEBUG_WRAPPER:
                 print >>sys.stderr, callable,
+            assert len(args) == len(callable.api_func.argtypes)
+            for i, (typ, is_wrapped) in argtypes_enum_ui:
+                arg = args[i]
+                if is_PyObject(typ) and is_wrapped:
+                    if arg:
+                        arg_conv = from_ref(space, rffi.cast(PyObject, arg))
+                    else:
+                        arg_conv = None
+                else:
+                    arg_conv = arg
+                boxed_args += (arg_conv, )
             state = space.fromcache(State)
-            %(middle)s
             try:
-                result = callable(space, %(args)s)
+                result = callable(space, *boxed_args)
                 if not we_are_translated() and DEBUG_WRAPPER:
                     print >>sys.stderr, " DONE"
             except OperationError, e:
@@ -597,8 +596,8 @@
             if failed:
                 error_value = callable.api_func.error_value
                 if error_value is CANNOT_FAIL:
-                    raise SystemError("The function '%%s' was not supposed to fail"
-                                      %% (callable.__name__,))
+                    raise SystemError("The function '%s' was not supposed to fail"
+                                      % (callable.__name__,))
                 retval = error_value
 
             elif is_PyObject(callable.api_func.restype):
@@ -625,13 +624,8 @@
             else:
                 print str(e)
                 pypy_debug_catch_fatal_exception()
+        rffi.stackcounter.stacks_counter -= 1
         return retval
-    """ % {"middle": middle, "args": arg_spec})
-    d = {}
-    d.update(locals())
-    d.update(globals())
-    exec source.compile() in d
-    wrapper = d['wrapper']
     callable._always_inline_ = 'try'
     wrapper.__name__ = "wrapper for %r" % (callable, )
     return wrapper
@@ -1029,7 +1023,7 @@
         export_struct(name, struct)
 
     for name, func in FUNCTIONS.iteritems():
-        deco = entrypoint("cpyext", func.argtypes, name)
+        deco = entrypoint_lowlevel("cpyext", func.argtypes, name, relax=True)
         deco(func.get_wrapper(space))
 
     setup_init_functions(eci, translating=True)
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
@@ -342,7 +342,7 @@
             return
 
         @cpython_api([PyObject, PyObject, PyObject], rffi.INT_real,
-                     error=-1, external=False)
+                     error=-1, external=True) # XXX should not be exported
         @func_renamer("cpyext_tp_setattro_%s" % (typedef.name,))
         def slot_tp_setattro(space, w_self, w_name, w_value):
             if w_value is not None:
diff --git a/rpython/annotator/description.py b/rpython/annotator/description.py
--- a/rpython/annotator/description.py
+++ b/rpython/annotator/description.py
@@ -215,8 +215,9 @@
         if len(self._cache) != 1:
             raise NoStandardGraph(self)
         [graph] = self._cache.values()
+        relax_sig_check = getattr(self.pyobj, "relax_sig_check", False)
         if (graph.signature != self.signature or
-            graph.defaults  != self.defaults):
+            graph.defaults  != self.defaults) and not relax_sig_check:
             raise NoStandardGraph(self)
         return graph
 
diff --git a/rpython/annotator/test/test_annrpython.py b/rpython/annotator/test/test_annrpython.py
--- a/rpython/annotator/test/test_annrpython.py
+++ b/rpython/annotator/test/test_annrpython.py
@@ -3542,6 +3542,16 @@
         s = a.build_types(f, [int])
         assert s.knowntype is int
 
+    def test_relax(self):
+        def f(*args):
+            return args[0] + args[1]
+        f.relax_sig_check = True
+        def g(x):
+            return f(x, x - x)
+        a = self.RPythonAnnotator()
+        s = a.build_types(g, [int])
+        assert a.bookkeeper.getdesc(f).getuniquegraph()
+
     def test_cannot_raise_ll_exception(self):
         from rpython.rtyper.annlowlevel import cast_instance_to_base_ptr
         #
diff --git a/rpython/rlib/entrypoint.py b/rpython/rlib/entrypoint.py
--- a/rpython/rlib/entrypoint.py
+++ b/rpython/rlib/entrypoint.py
@@ -5,13 +5,33 @@
 from rpython.rtyper.lltypesystem.lloperation import llop
 from rpython.rlib.objectmodel import we_are_translated
 
+
+def entrypoint_lowlevel(key, argtypes, c_name=None, relax=False):
+    """ Note: entrypoint should call llop.gc_stack_bottom on it's own.
+    That's necessary for making it work with asmgcc and hence JIT
+
+    If in doubt, use entrypoint().
+
+    if key == 'main' than it's included by default
+    """
+    from rpython.translator.tool.cbuild import ExternalCompilationInfo
+
+    def deco(func):
+        secondary_entrypoints.setdefault(key, []).append((func, argtypes))
+        if c_name is not None:
+            func.c_name = c_name
+        if relax:
+            func.relax_sig_check = True
+        func._compilation_info = ExternalCompilationInfo(
+            export_symbols=[c_name or func.func_name])
+        return func
+    return deco
+
+
 pypy_debug_catch_fatal_exception = rffi.llexternal('pypy_debug_catch_fatal_exception', [], lltype.Void)
 
 def entrypoint(key, argtypes, c_name=None):
-    """ Note: entrypoint should call llop.gc_stack_bottom on it's own.
-    That's necessary for making it work with asmgcc and hence JIT
-
-    if key == 'main' than it's included by default
+    """if key == 'main' than it's included by default
     """
     from rpython.translator.tool.cbuild import ExternalCompilationInfo
 
diff --git a/rpython/translator/c/test/test_genc.py b/rpython/translator/c/test/test_genc.py
--- a/rpython/translator/c/test/test_genc.py
+++ b/rpython/translator/c/test/test_genc.py
@@ -522,8 +522,9 @@
             f = getattr(self, "_f", None)
             if f is not None:
                 return f
-            f = lambda arg: self.func(arg)
+            f = lambda *args: self.func(*args)
             f.c_name = self.name
+            f.relax_sig_check = True
             f.__name__ = "WRAP%s" % (self.name, )
             self._f = f
             return f


More information about the pypy-commit mailing list