[pypy-svn] r79852 - in pypy/branch/fast-forward: . lib-python/modified-2.5.2/distutils pypy pypy/doc/config pypy/interpreter pypy/jit/codewriter pypy/jit/codewriter/test pypy/jit/metainterp pypy/jit/metainterp/optimizeopt pypy/jit/metainterp/test pypy/module/_stackless pypy/module/array/benchmark pypy/module/array/test pypy/module/cpyext pypy/module/cpyext/include pypy/module/cpyext/src pypy/module/cpyext/test pypy/module/pypyjit/test pypy/module/sys pypy/rlib pypy/rlib/test pypy/rpython/lltypesystem pypy/tool/release pypy/translator/goal pypy/translator/platform

afa at codespeak.net afa at codespeak.net
Mon Dec 6 17:27:37 CET 2010


Author: afa
Date: Mon Dec  6 17:27:34 2010
New Revision: 79852

Added:
   pypy/branch/fast-forward/pypy/module/cpyext/include/fileobject.h
      - copied unchanged from r79849, pypy/trunk/pypy/module/cpyext/include/fileobject.h
Modified:
   pypy/branch/fast-forward/   (props changed)
   pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/unixccompiler.py
   pypy/branch/fast-forward/pypy/   (props changed)
   pypy/branch/fast-forward/pypy/doc/config/objspace.usemodules.array.txt   (props changed)
   pypy/branch/fast-forward/pypy/interpreter/executioncontext.py
   pypy/branch/fast-forward/pypy/jit/codewriter/regalloc.py
   pypy/branch/fast-forward/pypy/jit/codewriter/test/test_regalloc.py
   pypy/branch/fast-forward/pypy/jit/metainterp/optimizefindnode.py
   pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/optimizer.py   (props changed)
   pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py
   pypy/branch/fast-forward/pypy/module/_stackless/interp_coroutine.py
   pypy/branch/fast-forward/pypy/module/array/benchmark/Makefile   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/intimg.c   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/intimgtst.c   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/intimgtst.py   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/loop.c   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/sum.c   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/sumtst.c   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/sumtst.py   (props changed)
   pypy/branch/fast-forward/pypy/module/array/test/test_array.py
   pypy/branch/fast-forward/pypy/module/array/test/test_array_old.py   (props changed)
   pypy/branch/fast-forward/pypy/module/cpyext/include/Python.h
   pypy/branch/fast-forward/pypy/module/cpyext/intobject.py
   pypy/branch/fast-forward/pypy/module/cpyext/object.py
   pypy/branch/fast-forward/pypy/module/cpyext/pyerrors.py
   pypy/branch/fast-forward/pypy/module/cpyext/pythonrun.py
   pypy/branch/fast-forward/pypy/module/cpyext/src/getargs.c
   pypy/branch/fast-forward/pypy/module/cpyext/state.py
   pypy/branch/fast-forward/pypy/module/cpyext/stubs.py
   pypy/branch/fast-forward/pypy/module/cpyext/test/test_cpyext.py
   pypy/branch/fast-forward/pypy/module/cpyext/test/test_intobject.py
   pypy/branch/fast-forward/pypy/module/cpyext/test/test_object.py
   pypy/branch/fast-forward/pypy/module/cpyext/test/test_pyerrors.py
   pypy/branch/fast-forward/pypy/module/pypyjit/test/test_pypy_c.py
   pypy/branch/fast-forward/pypy/module/sys/vm.py
   pypy/branch/fast-forward/pypy/rlib/rerased.py   (props changed)
   pypy/branch/fast-forward/pypy/rlib/test/test_rerased.py   (props changed)
   pypy/branch/fast-forward/pypy/rpython/lltypesystem/ll2ctypes.py
   pypy/branch/fast-forward/pypy/tool/release/package.py
   pypy/branch/fast-forward/pypy/translator/goal/app_main.py
   pypy/branch/fast-forward/pypy/translator/platform/darwin.py
Log:
Merge from trunk: -r79790:79849


Modified: pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/unixccompiler.py
==============================================================================
--- pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/unixccompiler.py	(original)
+++ pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/unixccompiler.py	Mon Dec  6 17:27:34 2010
@@ -121,7 +121,22 @@
                   }
 
     if sys.platform[:6] == "darwin":
+        import platform
+        if platform.machine() == 'i386':
+            if platform.architecture()[0] == '32bit':
+                arch = 'i386'
+            else:
+                arch = 'x86_64'
+        else:
+            # just a guess
+            arch = platform.machine()
         executables['ranlib'] = ["ranlib"]
+        executables['linker_so'] += ['-undefined', 'dynamic_lookup']
+
+        for k, v in executables.iteritems():
+            if v and v[0] == 'cc':
+                v += ['-arch', arch]
+
 
     # Needed for the filename generation methods provided by the base
     # class, CCompiler.  NB. whoever instantiates/uses a particular

Modified: pypy/branch/fast-forward/pypy/interpreter/executioncontext.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/executioncontext.py	(original)
+++ pypy/branch/fast-forward/pypy/interpreter/executioncontext.py	Mon Dec  6 17:27:34 2010
@@ -27,7 +27,6 @@
     def __init__(self, space):
         self.space = space
         self.topframeref = jit.vref_None
-        self.framestackdepth = 0
         # tracing: space.frame_trace_action.fire() must be called to ensure
         # that tracing occurs whenever self.w_tracefunc or self.is_tracing
         # is modified.
@@ -54,9 +53,6 @@
         return frame
 
     def enter(self, frame):
-        if self.framestackdepth > self.space.sys.recursionlimit:
-            raise self.space.prebuilt_recursion_error
-        self.framestackdepth += 1
         frame.f_backref = self.topframeref
         self.topframeref = jit.virtual_ref(frame)
 
@@ -66,7 +62,6 @@
                 self._trace(frame, 'leaveframe', self.space.w_None)
         finally:
             self.topframeref = frame.f_backref
-            self.framestackdepth -= 1
             jit.virtual_ref_finish(frame)
 
         if self.w_tracefunc is not None and not frame.hide():
@@ -80,7 +75,6 @@
 
         def __init__(self):
             self.topframe = None
-            self.framestackdepth = 0
             self.w_tracefunc = None
             self.profilefunc = None
             self.w_profilefuncarg = None
@@ -88,7 +82,6 @@
 
         def enter(self, ec):
             ec.topframeref = jit.non_virtual_ref(self.topframe)
-            ec.framestackdepth = self.framestackdepth
             ec.w_tracefunc = self.w_tracefunc
             ec.profilefunc = self.profilefunc
             ec.w_profilefuncarg = self.w_profilefuncarg
@@ -97,7 +90,6 @@
 
         def leave(self, ec):
             self.topframe = ec.gettopframe()
-            self.framestackdepth = ec.framestackdepth
             self.w_tracefunc = ec.w_tracefunc
             self.profilefunc = ec.profilefunc
             self.w_profilefuncarg = ec.w_profilefuncarg 
@@ -105,7 +97,6 @@
 
         def clear_framestack(self):
             self.topframe = None
-            self.framestackdepth = 0
 
         # the following interface is for pickling and unpickling
         def getstate(self, space):
@@ -121,17 +112,14 @@
                 self.topframe = space.interp_w(PyFrame, frames_w[-1])
             else:
                 self.topframe = None
-            self.framestackdepth = len(frames_w)
 
         def getframestack(self):
-            index = self.framestackdepth
-            lst = [None] * index
+            lst = []
             f = self.topframe
-            while index > 0:
-                index -= 1
-                lst[index] = f
+            while f is not None:
+                lst.append(f)
                 f = f.f_backref()
-            assert f is None
+            lst.reverse()
             return lst
         # coroutine: I think this is all, folks!
 

Modified: pypy/branch/fast-forward/pypy/jit/codewriter/regalloc.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/codewriter/regalloc.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/codewriter/regalloc.py	Mon Dec  6 17:27:34 2010
@@ -36,7 +36,7 @@
                             if isinstance(v1, Variable):
                                 die_at[v1] = i
                 if op.result is not None:
-                    die_at[op.result] = i
+                    die_at[op.result] = i + 1
             if isinstance(block.exitswitch, tuple):
                 for x in block.exitswitch:
                     die_at.pop(x, None)

Modified: pypy/branch/fast-forward/pypy/jit/codewriter/test/test_regalloc.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/codewriter/test/test_regalloc.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/codewriter/test/test_regalloc.py	Mon Dec  6 17:27:34 2010
@@ -281,22 +281,22 @@
         # this used to produce bogus code, containing these two
         # lines in the following broken order:
         #    last_exc_value -> %r0
-        #    ref_copy %r0 -> %r2    -- but expect to read the old value of %r0!
+        #    ref_copy %r0 -> %r1    -- but expect to read the old value of %r0!
         self.check_assembler(graph, """
             residual_call_r_r $<* fn bar>, <Descr>, R[%r0] -> %r1
             -live-
-            residual_call_ir_r $<* fn g>, <Descr>, I[%i0], R[] -> %r2
+            residual_call_ir_r $<* fn g>, <Descr>, I[%i0], R[] -> %r1
             -live-
             catch_exception L1
-            ref_return %r2
+            ref_return %r1
             ---
             L1:
             goto_if_exception_mismatch $<* struct object_vtable>, L2
-            ref_copy %r0 -> %r2
+            ref_copy %r0 -> %r1
             last_exc_value -> %r0
             residual_call_r_r $<* fn foo>, <Descr>, R[%r0] -> %r0
             -live-
-            ref_return %r2
+            ref_return %r1
             ---
             L2:
             reraise

Modified: pypy/branch/fast-forward/pypy/jit/metainterp/optimizefindnode.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/optimizefindnode.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/optimizefindnode.py	Mon Dec  6 17:27:34 2010
@@ -128,6 +128,7 @@
         assert isinstance(constbox, Const)
         node = InstanceNode()
         node.unique = UNIQUE_NO
+        node.escaped = True
         node.knownvaluebox = constbox
         self.nodes[box] = node
         return node

Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py	Mon Dec  6 17:27:34 2010
@@ -1954,6 +1954,15 @@
         """
         self.optimize_loop(ops, 'Virtual(node_vtable2, nextdescr=Not, otherdescr=Not)', expected)
 
+    def test_bug_4(self):
+        ops = """
+        [p9]
+        p30 = new_with_vtable(ConstClass(node_vtable))
+        setfield_gc(ConstPtr(myptr), p9, descr=nextdescr)
+        jump(p30)
+        """
+        self.optimize_loop(ops, 'Not', ops)
+
     def test_invalid_loop_1(self):
         ops = """
         [p1]

Modified: pypy/branch/fast-forward/pypy/module/_stackless/interp_coroutine.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/_stackless/interp_coroutine.py	(original)
+++ pypy/branch/fast-forward/pypy/module/_stackless/interp_coroutine.py	Mon Dec  6 17:27:34 2010
@@ -304,16 +304,19 @@
 
 def w_descr__framestack(space, self):
     assert isinstance(self, AppCoroutine)
-    index = self.subctx.framestackdepth
-    if not index:
-        return space.newtuple([])
-    items = [None] * index
+    counter = 0
     f = self.subctx.topframe
-    while index > 0:
-        index -= 1
-        items[index] = space.wrap(f)
+    while f is not None:
+        counter += 1
         f = f.f_backref()
-    assert f is None
+    items = [None] * counter
+    f = self.subctx.topframe
+    while f is not None:
+        counter -= 1
+        assert counter >= 0
+        items[counter] = space.wrap(f)
+        f = f.f_backref()
+    assert counter == 0
     return space.newtuple(items)
 
 def makeStaticMethod(module, classname, funcname):

Modified: pypy/branch/fast-forward/pypy/module/array/test/test_array.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/array/test/test_array.py	(original)
+++ pypy/branch/fast-forward/pypy/module/array/test/test_array.py	Mon Dec  6 17:27:34 2010
@@ -65,6 +65,7 @@
             raises(TypeError, self.array, tc, None)
 
     def test_value_range(self):
+        import sys
         values = (-129, 128, -128, 127, 0, 255, -1, 256,
                   -32768, 32767, -32769, 32768, 65535, 65536,
                   -2147483647, -2147483648, 2147483647, 4294967295, 4294967296,
@@ -89,7 +90,12 @@
                 a.append(v)
             for i, v in enumerate(ok * 2):
                 assert a[i] == v
-                assert type(a[i]) is pt
+                assert type(a[i]) is pt or (
+                    # A special case: we return ints in Array('I') on 64-bits,
+                    # whereas CPython returns longs.  The difference is
+                    # probably acceptable.
+                    tc == 'I' and
+                    sys.maxint > 2147483647 and type(a[i]) is int)
             for v in ok:
                 a[1] = v
                 assert a[0] == ok[0]

Modified: pypy/branch/fast-forward/pypy/module/cpyext/include/Python.h
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/include/Python.h	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/include/Python.h	Mon Dec  6 17:27:34 2010
@@ -8,6 +8,8 @@
 # include <stddef.h>
 # include <limits.h>
 # include <math.h>
+# include <errno.h>
+# include <unistd.h>
 # define Py_DEPRECATED(VERSION_UNUSED) __attribute__((__deprecated__))
 # define PyAPI_FUNC(RTYPE) RTYPE
 # define PyAPI_DATA(RTYPE) extern RTYPE
@@ -115,6 +117,7 @@
 #include "sliceobject.h"
 #include "datetime.h"
 #include "pystate.h"
+#include "fileobject.h"
 
 // XXX This shouldn't be included here
 #include "structmember.h"
@@ -132,4 +135,8 @@
 #define PyDoc_STR(str) ""
 #endif
 
+/* PyPy does not implement --with-fpectl */
+#define PyFPE_START_PROTECT(err_string, leave_stmt)
+#define PyFPE_END_PROTECT(v)
+
 #endif

Modified: pypy/branch/fast-forward/pypy/module/cpyext/intobject.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/intobject.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/intobject.py	Mon Dec  6 17:27:34 2010
@@ -1,5 +1,6 @@
 
 from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.interpreter.error import OperationError
 from pypy.module.cpyext.api import (
     cpython_api, build_type_checkers, PyObject,
     CONST_STRING, CANNOT_FAIL, Py_ssize_t)
@@ -20,6 +21,9 @@
     already one, and then return its value. If there is an error, -1 is
     returned, and the caller should check PyErr_Occurred() to find out whether
     there was an error, or whether the value just happened to be -1."""
+    if w_obj is None:
+        raise OperationError(space.w_TypeError,
+                             space.wrap("an integer is required, got NULL"))
     return space.int_w(space.int(w_obj))
 
 @cpython_api([PyObject], lltype.Unsigned, error=-1)
@@ -27,6 +31,9 @@
     """Return a C unsigned long representation of the contents of pylong.
     If pylong is greater than ULONG_MAX, an OverflowError is
     raised."""
+    if w_obj is None:
+        raise OperationError(space.w_TypeError,
+                             space.wrap("an integer is required, got NULL"))
     return space.uint_w(space.int(w_obj))
 
 @cpython_api([PyObject], rffi.ULONG, error=-1)
@@ -54,6 +61,9 @@
     PyLongObject, if it is not already one, and then return its value as
     Py_ssize_t.
     """
+    if w_obj is None:
+        raise OperationError(space.w_TypeError,
+                             space.wrap("an integer is required, got NULL"))
     return space.int_w(w_obj) # XXX this is wrong on win64
 
 @cpython_api([Py_ssize_t], PyObject)
@@ -85,4 +95,3 @@
     if pend:
         pend[0] = rffi.ptradd(str, len(s))
     return space.call_function(space.w_int, w_str, w_base)
-

Modified: pypy/branch/fast-forward/pypy/module/cpyext/object.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/object.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/object.py	Mon Dec  6 17:27:34 2010
@@ -2,12 +2,13 @@
 from pypy.module.cpyext.api import (
     cpython_api, generic_cpy_call, CANNOT_FAIL, Py_ssize_t, Py_ssize_tP,
     PyVarObject, Py_TPFLAGS_HEAPTYPE, Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT,
-    Py_GE, CONST_STRING, FILEP, fwrite)
+    Py_GE, CONST_STRING, FILEP, fwrite, build_type_checkers)
 from pypy.module.cpyext.pyobject import (
     PyObject, PyObjectP, create_ref, from_ref, Py_IncRef, Py_DecRef,
     track_reference, get_typedescr, RefcountState)
 from pypy.module.cpyext.typeobject import PyTypeObjectPtr
 from pypy.module.cpyext.pyerrors import PyErr_NoMemory, PyErr_BadInternalCall
+from pypy.module._file.interp_file import W_File
 from pypy.objspace.std.objectobject import W_ObjectObject
 from pypy.objspace.std.typeobject import W_TypeObject
 from pypy.interpreter.error import OperationError
@@ -428,6 +429,34 @@
         rffi.free_nonmovingbuffer(data, buf)
     return 0
 
+PyFile_Check, PyFile_CheckExact = build_type_checkers("File", W_File)
+
+ at cpython_api([PyObject, rffi.INT_real], PyObject)
+def PyFile_GetLine(space, w_obj, n):
+    """
+    Equivalent to p.readline([n]), this function reads one line from the
+    object p.  p may be a file object or any object with a readline()
+    method.  If n is 0, exactly one line is read, regardless of the length of
+    the line.  If n is greater than 0, no more than n bytes will be read
+    from the file; a partial line can be returned.  In both cases, an empty string
+    is returned if the end of the file is reached immediately.  If n is less than
+    0, however, one line is read regardless of length, but EOFError is
+    raised if the end of the file is reached immediately."""
+    try:
+        w_readline = space.getattr(w_obj, space.wrap('readline'))
+    except OperationError:
+        raise OperationError(
+            space.w_TypeError, space.wrap(
+            "argument must be a file, or have a readline() method."))
+
+    n = rffi.cast(lltype.Signed, n)
+    if space.is_true(space.gt(space.wrap(n), space.wrap(0))):
+        return space.call_function(w_readline, space.wrap(n))
+    elif space.is_true(space.lt(space.wrap(n), space.wrap(0))):
+        return space.call_function(w_readline)
+    else:
+        # XXX Raise EOFError as specified
+        return space.call_function(w_readline)
 @cpython_api([CONST_STRING, CONST_STRING], PyObject)
 def PyFile_FromString(space, filename, mode):
     """
@@ -437,4 +466,3 @@
     w_filename = space.wrap(rffi.charp2str(filename))
     w_mode = space.wrap(rffi.charp2str(mode))
     return space.call_method(space.builtin, 'file', w_filename, w_mode)
-

Modified: pypy/branch/fast-forward/pypy/module/cpyext/pyerrors.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/pyerrors.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/pyerrors.py	Mon Dec  6 17:27:34 2010
@@ -5,7 +5,7 @@
 from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL, CONST_STRING
 from pypy.module.exceptions.interp_exceptions import W_RuntimeWarning
 from pypy.module.cpyext.pyobject import (
-    PyObject, PyObjectP, make_ref, Py_DecRef, borrow_from)
+    PyObject, PyObjectP, make_ref, from_ref, Py_DecRef, borrow_from)
 from pypy.module.cpyext.state import State
 from pypy.module.cpyext.import_ import PyImport_Import
 from pypy.rlib.rposix import get_errno
@@ -80,6 +80,21 @@
     Py_DecRef(space, w_value)
     Py_DecRef(space, w_traceback)
 
+ at cpython_api([PyObjectP, PyObjectP, PyObjectP], lltype.Void)
+def PyErr_NormalizeException(space, exc_p, val_p, tb_p):
+    """Under certain circumstances, the values returned by PyErr_Fetch() below
+    can be "unnormalized", meaning that *exc is a class object but *val is
+    not an instance of the  same class.  This function can be used to instantiate
+    the class in that case.  If the values are already normalized, nothing happens.
+    The delayed normalization is implemented to improve performance."""
+    operr = OperationError(from_ref(space, exc_p[0]),
+                           from_ref(space, val_p[0]))
+    operr.normalize_exception(space)
+    Py_DecRef(space, exc_p[0])
+    Py_DecRef(space, val_p[0])
+    exc_p[0] = make_ref(space, operr.w_type)
+    val_p[0] = make_ref(space, operr.get_w_value(space))
+
 @cpython_api([], lltype.Void)
 def PyErr_BadArgument(space):
     """This is a shorthand for PyErr_SetString(PyExc_TypeError, message), where
@@ -114,10 +129,29 @@
     function around a system call can write return PyErr_SetFromErrno(type);
     when the system call returns an error.
     Return value: always NULL."""
+    PyErr_SetFromErrnoWithFilename(space, w_type,
+                                   lltype.nullptr(rffi.CCHARP.TO))
+
+ at cpython_api([PyObject, rffi.CCHARP], PyObject)
+def PyErr_SetFromErrnoWithFilename(space, w_type, llfilename):
+    """Similar to PyErr_SetFromErrno(), with the additional behavior that if
+    filename is not NULL, it is passed to the constructor of type as a third
+    parameter.  In the case of exceptions such as IOError and OSError,
+    this is used to define the filename attribute of the exception instance.
+    Return value: always NULL."""
     # XXX Doesn't actually do anything with PyErr_CheckSignals.
     errno = get_errno()
     msg = os.strerror(errno)
-    w_error = space.call_function(w_type, space.wrap(errno), space.wrap(msg))
+    if llfilename:
+        w_filename = rffi.charp2str(llfilename)
+        w_error = space.call_function(w_type,
+                                      space.wrap(errno),
+                                      space.wrap(msg),
+                                      space.wrap(w_filename))
+    else:
+        w_error = space.call_function(w_type,
+                                      space.wrap(errno),
+                                      space.wrap(msg))
     raise OperationError(w_type, w_error)
 
 @cpython_api([], rffi.INT_real, error=-1)

Modified: pypy/branch/fast-forward/pypy/module/cpyext/pythonrun.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/pythonrun.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/pythonrun.py	Mon Dec  6 17:27:34 2010
@@ -1,6 +1,16 @@
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL
+from pypy.module.cpyext.state import State
 
 @cpython_api([], rffi.INT_real, error=CANNOT_FAIL)
 def Py_IsInitialized(space):
     return 1
+
+ at cpython_api([], rffi.CCHARP, error=CANNOT_FAIL)
+def Py_GetProgramName(space):
+    """
+    Return the program name set with Py_SetProgramName(), or the default.
+    The returned string points into static storage; the caller should not modify its
+    value."""
+    return space.fromcache(State).get_programname()
+

Modified: pypy/branch/fast-forward/pypy/module/cpyext/src/getargs.c
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/src/getargs.c	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/src/getargs.c	Mon Dec  6 17:27:34 2010
@@ -445,18 +445,22 @@
 	for (i = 0; i < n; i++) {
 		char *msg;
 		PyObject *item;
-		item = PySequence_GetItem(arg, i);
+		/* CPython uses PySequence_GetItem() and Py_XDECREF() here,
+		   exposing a crash (see http://bugs.python.org/issue6083).
+		   It always crashes with PyPy, so we apply the fix being
+		   discussed: we only allow a tuple. */
+		item = PyTuple_GetItem(arg, i);
 		if (item == NULL) {
 			PyErr_Clear();
 			levels[0] = i+1;
 			levels[1] = 0;
-			strncpy(msgbuf, "is not retrievable", bufsize);
+			strncpy(msgbuf, "is not retrievable (subargument "
+				        "must be a real tuple with PyPy)",
+				        bufsize);
 			return msgbuf;
 		}
 		msg = convertitem(item, &format, p_va, flags, levels+1, 
 				  msgbuf, bufsize, freelist);
-		/* PySequence_GetItem calls tp->sq_item, which INCREFs */
-		Py_XDECREF(item);
 		if (msg != NULL) {
 			levels[0] = i+1;
 			return msg;

Modified: pypy/branch/fast-forward/pypy/module/cpyext/state.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/state.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/state.py	Mon Dec  6 17:27:34 2010
@@ -9,6 +9,7 @@
     def __init__(self, space):
         self.space = space
         self.reset()
+        self.programname = lltype.nullptr(rffi.CCHARP.TO)
 
     def reset(self):
         from pypy.module.cpyext.modsupport import PyMethodDef
@@ -82,3 +83,16 @@
         for func in INIT_FUNCTIONS:
             func(space)
             self.check_and_raise_exception()
+
+    def get_programname(self):
+        if not self.programname:
+            space = self.space
+            argv = space.sys.get('argv')
+            if space.int_w(space.len(argv)):
+                argv0 = space.getitem(argv, space.wrap(0))
+                progname = space.str_w(argv0)
+            else:
+                progname = "pypy"
+            self.programname = rffi.str2charp(progname)
+            lltype.render_immortal(self.programname)
+        return self.programname

Modified: pypy/branch/fast-forward/pypy/module/cpyext/stubs.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/stubs.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/stubs.py	Mon Dec  6 17:27:34 2010
@@ -597,24 +597,6 @@
     """
     raise NotImplementedError
 
- at cpython_api([PyObjectP, PyObjectP, PyObjectP], lltype.Void)
-def PyErr_NormalizeException(space, exc, val, tb):
-    """Under certain circumstances, the values returned by PyErr_Fetch() below
-    can be "unnormalized", meaning that *exc is a class object but *val is
-    not an instance of the  same class.  This function can be used to instantiate
-    the class in that case.  If the values are already normalized, nothing happens.
-    The delayed normalization is implemented to improve performance."""
-    raise NotImplementedError
-
- at cpython_api([PyObject, rffi.CCHARP], PyObject)
-def PyErr_SetFromErrnoWithFilename(space, type, filename):
-    """Similar to PyErr_SetFromErrno(), with the additional behavior that if
-    filename is not NULL, it is passed to the constructor of type as a third
-    parameter.  In the case of exceptions such as IOError and OSError,
-    this is used to define the filename attribute of the exception instance.
-    Return value: always NULL."""
-    raise NotImplementedError
-
 @cpython_api([rffi.INT_real], PyObject)
 def PyErr_SetFromWindowsErr(space, ierr):
     """This is a convenience function to raise WindowsError. If called with
@@ -723,21 +705,6 @@
     successful invocation of Py_EnterRecursiveCall()."""
     raise NotImplementedError
 
- at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
-def PyFile_Check(space, p):
-    """Return true if its argument is a PyFileObject or a subtype of
-    PyFileObject.
-    
-    Allowed subtypes to be accepted."""
-    raise NotImplementedError
-
- at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
-def PyFile_CheckExact(space, p):
-    """Return true if its argument is a PyFileObject, but not a subtype of
-    PyFileObject.
-    """
-    raise NotImplementedError
-
 @cpython_api([FILE, rffi.CCHARP, rffi.CCHARP, rffi.INT_real], PyObject)
 def PyFile_FromFile(space, fp, name, mode, close):
     """Create a new PyFileObject from the already-open standard C file
@@ -771,22 +738,6 @@
     """
     raise NotImplementedError
 
- at cpython_api([PyObject, rffi.INT_real], PyObject)
-def PyFile_GetLine(space, p, n):
-    """
-    
-    
-    
-    Equivalent to p.readline([n]), this function reads one line from the
-    object p.  p may be a file object or any object with a readline()
-    method.  If n is 0, exactly one line is read, regardless of the length of
-    the line.  If n is greater than 0, no more than n bytes will be read
-    from the file; a partial line can be returned.  In both cases, an empty string
-    is returned if the end of the file is reached immediately.  If n is less than
-    0, however, one line is read regardless of length, but EOFError is
-    raised if the end of the file is reached immediately."""
-    raise NotImplementedError
-
 @cpython_api([PyObject], PyObject)
 def PyFile_Name(space, p):
     """Return the name of the file specified by p as a string object."""
@@ -1310,17 +1261,6 @@
     raise NotImplementedError
 
 @cpython_api([], rffi.CCHARP, error=CANNOT_FAIL)
-def Py_GetProgramName(space, ):
-    """
-    
-    
-    
-    Return the program name set with Py_SetProgramName(), or the default.
-    The returned string points into static storage; the caller should not modify its
-    value."""
-    raise NotImplementedError
-
- at cpython_api([], rffi.CCHARP, error=CANNOT_FAIL)
 def Py_GetPrefix(space, ):
     """Return the prefix for installed platform-independent files. This is derived
     through a number of complicated rules from the program name set with

Modified: pypy/branch/fast-forward/pypy/module/cpyext/test/test_cpyext.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/test/test_cpyext.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/test/test_cpyext.py	Mon Dec  6 17:27:34 2010
@@ -691,3 +691,19 @@
         assert mod.get_names() == ('cell', 'module', 'property',
                                    'staticmethod',
                                    'builtin_function_or_method')
+
+    def test_get_programname(self):
+        mod = self.import_extension('foo', [
+            ('get_programname', 'METH_NOARGS',
+             '''
+             char* name1 = Py_GetProgramName();
+             char* name2 = Py_GetProgramName();
+             if (name1 != name2)
+                 Py_RETURN_FALSE;
+             return PyString_FromString(name1);
+             '''
+             ),
+            ])
+        p = mod.get_programname()
+        print p
+        assert 'py' in p

Modified: pypy/branch/fast-forward/pypy/module/cpyext/test/test_intobject.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/test/test_intobject.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/test/test_intobject.py	Mon Dec  6 17:27:34 2010
@@ -20,6 +20,10 @@
         assert api.PyErr_Occurred() is space.w_TypeError
         api.PyErr_Clear()
 
+        assert api.PyInt_AsLong(None) == -1
+        assert api.PyErr_Occurred() is space.w_TypeError
+        api.PyErr_Clear()
+
         assert api.PyInt_AsUnsignedLong(space.wrap(sys.maxint)) == sys.maxint
         assert api.PyInt_AsUnsignedLong(space.wrap(-5)) == sys.maxint * 2 + 1
         assert api.PyErr_Occurred() is space.w_ValueError

Modified: pypy/branch/fast-forward/pypy/module/cpyext/test/test_object.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/test/test_object.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/test/test_object.py	Mon Dec  6 17:27:34 2010
@@ -4,7 +4,7 @@
 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.module.cpyext.api import Py_LT, Py_LE, Py_NE, Py_EQ,\
-    Py_GE, Py_GT
+    Py_GE, Py_GT, fopen, fclose, fwrite
 from pypy.tool.udir import udir
 
 class TestObject(BaseApiTest):
@@ -188,10 +188,45 @@
         rffi.free_charp(filename)
         rffi.free_charp(mode)
 
+        assert api.PyFile_Check(w_file)
+        assert api.PyFile_CheckExact(w_file)
+        assert not api.PyFile_Check(space.wrap("text"))
+
         space.call_method(w_file, "write", space.wrap("text"))
         space.call_method(w_file, "close")
         assert (udir / "_test_file").read() == "text"
 
+    def test_file_getline(self, space, api):
+        filename = rffi.str2charp(str(udir / "_test_file"))
+
+        mode = rffi.str2charp("w")
+        w_file = api.PyFile_FromString(filename, mode)
+        space.call_method(w_file, "write",
+                          space.wrap("line1\nline2\nline3\nline4"))
+        space.call_method(w_file, "close")
+
+        rffi.free_charp(mode)
+        mode = rffi.str2charp("r")
+        w_file = api.PyFile_FromString(filename, mode)
+        rffi.free_charp(filename)
+        rffi.free_charp(mode)
+
+        w_line = api.PyFile_GetLine(w_file, 0)
+        assert space.str_w(w_line) == "line1\n"
+
+        w_line = api.PyFile_GetLine(w_file, 4)
+        assert space.str_w(w_line) == "line"
+
+        w_line = api.PyFile_GetLine(w_file, 0)
+        assert space.str_w(w_line) == "2\n"
+
+        # XXX We ought to raise an EOFError here, but don't
+        w_line = api.PyFile_GetLine(w_file, -1)
+        # assert api.PyErr_Occurred() is space.w_EOFError
+        assert space.str_w(w_line) == "line3\n"
+
+        space.call_method(w_file, "close")
+
 class AppTestObject(AppTestCpythonExtensionBase):
     def setup_class(cls):
         AppTestCpythonExtensionBase.setup_class.im_func(cls)

Modified: pypy/branch/fast-forward/pypy/module/cpyext/test/test_pyerrors.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/test/test_pyerrors.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/test/test_pyerrors.py	Mon Dec  6 17:27:34 2010
@@ -129,6 +129,41 @@
             ])
         assert module.check_error()
 
+
+    def test_normalize(self):
+        module = self.import_extension('foo', [
+            ("check_error", "METH_NOARGS",
+             '''
+             PyObject *type, *val, *tb;
+             PyErr_SetString(PyExc_TypeError, "message");
+
+             PyErr_Fetch(&type, &val, &tb);
+             if (type != PyExc_TypeError)
+                 Py_RETURN_FALSE;
+             if (!PyString_Check(val))
+                 Py_RETURN_FALSE;
+             /* Normalize */
+             PyErr_NormalizeException(&type, &val, &tb);
+             if (type != PyExc_TypeError)
+                 Py_RETURN_FALSE;
+             if (val->ob_type != PyExc_TypeError)
+                 Py_RETURN_FALSE;
+
+             /* Normalize again */
+             PyErr_NormalizeException(&type, &val, &tb);
+             if (type != PyExc_TypeError)
+                 Py_RETURN_FALSE;
+             if (val->ob_type != PyExc_TypeError)
+                 Py_RETURN_FALSE;
+
+             PyErr_Restore(type, val, tb);
+             PyErr_Clear();
+             Py_RETURN_TRUE;
+             '''
+             ),
+            ])
+        assert module.check_error()
+
     def test_SetFromErrno(self):
         import sys
         if sys.platform != 'win32':
@@ -149,3 +184,26 @@
         except OSError, e:
             assert e.errno == errno.EBADF
             assert e.strerror == os.strerror(errno.EBADF)
+            assert e.filename == None
+
+    def test_SetFromErrnoWithFilename(self):
+        import sys
+        if sys.platform != 'win32':
+            skip("callbacks through ll2ctypes modify errno")
+        import errno, os
+
+        module = self.import_extension('foo', [
+                ("set_from_errno", "METH_NOARGS",
+                 '''
+                 errno = EBADF;
+                 PyErr_SetFromErrnoWithFilename(PyExc_OSError, "blyf");
+                 return NULL;
+                 '''),
+                ],
+                prologue="#include <errno.h>")
+        try:
+            module.set_from_errno()
+        except OSError, e:
+            assert e.filename == "blyf"
+            assert e.errno == errno.EBADF
+            assert e.strerror == os.strerror(errno.EBADF)

Modified: pypy/branch/fast-forward/pypy/module/pypyjit/test/test_pypy_c.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/pypyjit/test/test_pypy_c.py	(original)
+++ pypy/branch/fast-forward/pypy/module/pypyjit/test/test_pypy_c.py	Mon Dec  6 17:27:34 2010
@@ -885,11 +885,14 @@
     def test_array_sum(self):
         for tc, maxops in zip('bhilBHILfd', (38,) * 6 + (40, 40, 41, 38)):
             res = 19352859
-            if tc in 'IL':
+            if tc == 'L':
                 res = long(res)
             elif tc in 'fd':
                 res = float(res)
-            
+            elif tc == 'I' and sys.maxint == 2147483647:
+                res = long(res)
+                # note: in CPython we always get longs here, even on 64-bits
+
             self.run_source('''
             from array import array
 
@@ -937,11 +940,14 @@
             print '='*65
             print '='*20, 'running test for tc=%r' % (tc,), '='*20
             res = 73574560
-            if tc in 'IL':
+            if tc == 'L':
                 res = long(res)
             elif tc in 'fd':
                 res = float(res)
-            
+            elif tc == 'I' and sys.maxint == 2147483647:
+                res = long(res)
+                # note: in CPython we always get longs here, even on 64-bits
+
             self.run_source('''
             from array import array
 

Modified: pypy/branch/fast-forward/pypy/module/sys/vm.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/sys/vm.py	(original)
+++ pypy/branch/fast-forward/pypy/module/sys/vm.py	Mon Dec  6 17:27:34 2010
@@ -42,27 +42,21 @@
         f = ec.getnextframe_nohidden(f)
     return space.wrap(f)
 
-# directly from the C code in ceval.c, might be moved somewhere else.
-
 def setrecursionlimit(space, w_new_limit):
-    """Set the maximum depth of the Python interpreter stack to n.  This
-limit prevents infinite recursion from causing an overflow of the C
-stack and crashing Python.  The highest possible limit is platform
-dependent."""
+    """DEPRECATED on PyPy. Will issue warning and not work
+    """
     new_limit = space.int_w(w_new_limit)
     if new_limit <= 0:
         raise OperationError(space.w_ValueError,
                              space.wrap("recursion limit must be positive"))
     # global recursion_limit
     # we need to do it without writing globals.
+    space.warn('setrecursionlimit deprecated', space.w_DeprecationWarning)
     space.sys.recursionlimit = new_limit
 
 def getrecursionlimit(space):
-    """Return the current value of the recursion limit, the maximum depth
-    of the Python interpreter stack.  This limit prevents infinite
-    recursion from causing an overflow of the C stack and crashing Python.
+    """DEPRECATED on PyPy. Will issue warning and not work
     """
-
     return space.wrap(space.sys.recursionlimit)
 
 def setcheckinterval(space, interval):

Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/ll2ctypes.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/lltypesystem/ll2ctypes.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/ll2ctypes.py	Mon Dec  6 17:27:34 2010
@@ -413,6 +413,7 @@
     subcls = get_common_subclass(mixin_cls, instance.__class__)
     instance.__class__ = subcls
     instance._storage = ctypes_storage
+    assert ctypes_storage   # null pointer?
 
 class _parentable_mixin(object):
     """Mixin added to _parentable containers when they become ctypes-based.

Modified: pypy/branch/fast-forward/pypy/tool/release/package.py
==============================================================================
--- pypy/branch/fast-forward/pypy/tool/release/package.py	(original)
+++ pypy/branch/fast-forward/pypy/tool/release/package.py	Mon Dec  6 17:27:34 2010
@@ -78,7 +78,7 @@
     old_dir = os.getcwd()
     try:
         os.chdir(str(builddir))
-        os.system("strip " + str(archive_pypy_c))    # ignore errors
+        os.system("strip -x " + str(archive_pypy_c))    # ignore errors
         if USE_TARFILE_MODULE:
             import tarfile
             tf = tarfile.open(str(builddir.join(name + '.tar.bz2')), 'w:bz2')

Modified: pypy/branch/fast-forward/pypy/translator/goal/app_main.py
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/goal/app_main.py	(original)
+++ pypy/branch/fast-forward/pypy/translator/goal/app_main.py	Mon Dec  6 17:27:34 2010
@@ -383,8 +383,9 @@
                      cmd=None,
                      **ignored):
     # with PyPy in top of CPython we can only have around 100 
-    # but we need more in the translated PyPy for the compiler package 
-    sys.setrecursionlimit(5000)
+    # but we need more in the translated PyPy for the compiler package
+    if '__pypy__' not in sys.builtin_module_names:
+        sys.setrecursionlimit(5000)
 
     if unbuffered:
         set_unbuffered_io()

Modified: pypy/branch/fast-forward/pypy/translator/platform/darwin.py
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/platform/darwin.py	(original)
+++ pypy/branch/fast-forward/pypy/translator/platform/darwin.py	Mon Dec  6 17:27:34 2010
@@ -11,8 +11,10 @@
     shared_only = ()
 
     so_ext = 'so'
-    
-    default_cc = 'gcc'
+
+    # NOTE: GCC 4.2 will fail at runtime due to subtle issues, possibly
+    # related to GC roots. Using LLVM-GCC or Clang will break the build.
+    default_cc = 'gcc-4.0'
 
     def __init__(self, cc=None):
         if cc is None:
@@ -87,4 +89,3 @@
     link_flags = ('-arch', 'x86_64', '-mmacosx-version-min=10.4')
     cflags = ('-arch', 'x86_64', '-O3', '-fomit-frame-pointer',
               '-mmacosx-version-min=10.4')
-    default_cc = 'gcc-4.0'



More information about the Pypy-commit mailing list