[pypy-commit] pypy guard-compatible: merge default

cfbolz pypy.commits at gmail.com
Tue Jun 28 12:09:14 EDT 2016


Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: guard-compatible
Changeset: r85440:790c399e5c6b
Date: 2016-06-28 18:08 +0200
http://bitbucket.org/pypy/pypy/changeset/790c399e5c6b/

Log:	merge default

diff --git a/pypy/doc/config/commandline.txt b/pypy/doc/config/commandline.txt
--- a/pypy/doc/config/commandline.txt
+++ b/pypy/doc/config/commandline.txt
@@ -9,7 +9,7 @@
 PyPy Python interpreter options
 -------------------------------
 
-The following options can be used after ``translate.py
+The following options can be used after ``rpython
 targetpypystandalone`` or as options to ``py.py``.
 
 .. GENERATE: objspace
@@ -22,7 +22,7 @@
 General translation options
 ---------------------------
 
-The following are options of ``translate.py``.  They must be
+The following are options of ``bin/rpython``.  They must be
 given before the ``targetxxx`` on the command line.
 
 * `--opt -O:`__ set the optimization level `[0, 1, size, mem, 2, 3]`
diff --git a/pypy/doc/config/index.rst b/pypy/doc/config/index.rst
--- a/pypy/doc/config/index.rst
+++ b/pypy/doc/config/index.rst
@@ -15,12 +15,12 @@
 
     ./py.py <`objspace options`_>
 
-and the ``translate.py`` translation entry
+and the ``rpython/bin/rpython`` translation entry
 point which takes arguments of this form:
 
 .. parsed-literal::
 
-    ./translate.py <`translation options`_> <target>
+    ./rpython/bin/rpython <`translation options`_> <target>
 
 For the common case of ``<target>`` being ``targetpypystandalone.py``,
 you can then pass the `object space options`_ after
@@ -28,7 +28,7 @@
 
 .. parsed-literal::
 
-    ./translate.py <`translation options`_> targetpypystandalone.py <`objspace options`_>
+    ./rpython/bin/rpython <`translation options`_> targetpypystandalone.py <`objspace options`_>
 
 There is an `overview`_ of all command line arguments that can be
 passed in either position.
diff --git a/pypy/doc/config/opt.rst b/pypy/doc/config/opt.rst
--- a/pypy/doc/config/opt.rst
+++ b/pypy/doc/config/opt.rst
@@ -4,8 +4,8 @@
 This meta-option selects a default set of optimization
 settings to use during a translation.  Usage::
 
-    translate.py --opt=#
-    translate.py -O#
+    bin/rpython --opt=#
+    bin/rpython -O#
 
 where ``#`` is the desired optimization level.  The valid choices are:
 
diff --git a/pypy/doc/config/translation.dont_write_c_files.txt b/pypy/doc/config/translation.dont_write_c_files.txt
--- a/pypy/doc/config/translation.dont_write_c_files.txt
+++ b/pypy/doc/config/translation.dont_write_c_files.txt
@@ -1,4 +1,4 @@
 write the generated C files to ``/dev/null`` instead of to the disk. Useful if
-you want to use translate.py as a benchmark and don't want to access the disk.
+you want to use translation as a benchmark and don't want to access the disk.
 
 .. _`translation documentation`: ../translation.html
diff --git a/pypy/doc/config/translation.fork_before.txt b/pypy/doc/config/translation.fork_before.txt
--- a/pypy/doc/config/translation.fork_before.txt
+++ b/pypy/doc/config/translation.fork_before.txt
@@ -1,4 +1,4 @@
 This is an option mostly useful when working on the PyPy toolchain. If you use
-it, translate.py will fork before the specified phase. If the translation
+it, translation will fork before the specified phase. If the translation
 crashes after that fork, you can fix the bug in the toolchain, and continue
 translation at the fork-point.
diff --git a/pypy/doc/cppyy.rst b/pypy/doc/cppyy.rst
--- a/pypy/doc/cppyy.rst
+++ b/pypy/doc/cppyy.rst
@@ -122,7 +122,7 @@
     $ hg up reflex-support         # optional
 
     # This example shows python, but using pypy-c is faster and uses less memory
-    $ python rpython/translator/goal/translate.py --opt=jit pypy/goal/targetpypystandalone --withmod-cppyy
+    $ python rpython/bin/rpython --opt=jit pypy/goal/targetpypystandalone --withmod-cppyy
 
 This will build a ``pypy-c`` that includes the cppyy module, and through that,
 Reflex support.
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
@@ -48,3 +48,8 @@
 Bug fix: if ``socket.socket()`` failed, the ``socket.error`` did not show
 the errno of the failing system call, but instead some random previous
 errno.
+
+.. branch: PyTuple_Type-subclass
+
+Refactor PyTupleObject to look like cpython's and allow subclassing 
+PyTuple_Type
diff --git a/pypy/interpreter/astcompiler/tools/asdl_py.py b/pypy/interpreter/astcompiler/tools/asdl_py.py
--- a/pypy/interpreter/astcompiler/tools/asdl_py.py
+++ b/pypy/interpreter/astcompiler/tools/asdl_py.py
@@ -400,7 +400,7 @@
     if not (space.isinstance_w(w_obj, space.w_str) or
             space.isinstance_w(w_obj, space.w_unicode)):
         raise oefmt(space.w_TypeError,
-                   "AST string must be of type str or unicode")
+                    "AST string must be of type str or unicode")
     return w_obj
 
 def get_field(space, w_node, name, optional):
diff --git a/pypy/module/cpyext/bufferobject.py b/pypy/module/cpyext/bufferobject.py
--- a/pypy/module/cpyext/bufferobject.py
+++ b/pypy/module/cpyext/bufferobject.py
@@ -79,5 +79,5 @@
         Py_DecRef(space, py_buf.c_b_base)
     else:
         rffi.free_charp(rffi.cast(rffi.CCHARP, py_buf.c_b_ptr))
-    from pypy.module.cpyext.object import PyObject_dealloc
-    PyObject_dealloc(space, py_obj)
+    from pypy.module.cpyext.object import _dealloc
+    _dealloc(space, py_obj)
diff --git a/pypy/module/cpyext/bytearrayobject.py b/pypy/module/cpyext/bytearrayobject.py
--- a/pypy/module/cpyext/bytearrayobject.py
+++ b/pypy/module/cpyext/bytearrayobject.py
@@ -26,54 +26,10 @@
 PyByteArrayObjectStruct = lltype.ForwardReference()
 PyByteArrayObject = lltype.Ptr(PyByteArrayObjectStruct)
 PyByteArrayObjectFields = PyVarObjectFields 
-#    (("ob_exports", rffi.INT), ("ob_alloc", rffi.LONG), ("ob_bytes", rffi.CCHARP))
 cpython_struct("PyByteArrayObject", PyByteArrayObjectFields, PyByteArrayObjectStruct)
 
- at bootstrap_function
-def init_bytearrayobject(space):
-    "Type description of PyByteArrayObject"
-    #make_typedescr(space.w_bytearray.layout.typedef,
-    #               basestruct=PyByteArrayObject.TO,
-    #               attach=bytearray_attach,
-    #               dealloc=bytearray_dealloc,
-    #               realize=bytearray_realize)
-
 PyByteArray_Check, PyByteArray_CheckExact = build_type_checkers("ByteArray", "w_bytearray")
 
-# XXX dead code to be removed
-#def bytearray_attach(space, py_obj, w_obj):
-#    """
-#    Fills a newly allocated PyByteArrayObject with the given bytearray object
-#    """
-#    py_ba = rffi.cast(PyByteArrayObject, py_obj)
-#    py_ba.c_ob_size = len(space.str_w(w_obj))
-#    py_ba.c_ob_bytes = lltype.nullptr(rffi.CCHARP.TO)
-#    py_ba.c_ob_exports = rffi.cast(rffi.INT, 0)
-
-#def bytearray_realize(space, py_obj):
-#    """
-#    Creates the bytearray in the interpreter. 
-#    """
-#    py_ba = rffi.cast(PyByteArrayObject, py_obj)
-#    if not py_ba.c_ob_bytes:
-#        py_ba.c_buffer = lltype.malloc(rffi.CCHARP.TO, py_ba.c_ob_size + 1,
-#                                    flavor='raw', zero=True)
-#    s = rffi.charpsize2str(py_ba.c_ob_bytes, py_ba.c_ob_size)
-#    w_obj = space.wrap(s)
-#    py_ba.c_ob_exports = rffi.cast(rffi.INT, 0)
-#    track_reference(space, py_obj, w_obj)
-#    return w_obj
-
-#@cpython_api([PyObject], lltype.Void, header=None)
-#def bytearray_dealloc(space, py_obj):
-#    """Frees allocated PyByteArrayObject resources.
-#    """
-#    py_ba = rffi.cast(PyByteArrayObject, py_obj)
-#    if py_ba.c_ob_bytes:
-#        lltype.free(py_ba.c_ob_bytes, flavor="raw")
-#    from pypy.module.cpyext.object import PyObject_dealloc
-#    PyObject_dealloc(space, py_obj)
-
 #_______________________________________________________________________
 
 @cpython_api([PyObject], PyObject, result_is_ll=True)
diff --git a/pypy/module/cpyext/bytesobject.py b/pypy/module/cpyext/bytesobject.py
--- a/pypy/module/cpyext/bytesobject.py
+++ b/pypy/module/cpyext/bytesobject.py
@@ -11,7 +11,7 @@
 from pypy.objspace.std.bytesobject import W_BytesObject
 
 ##
-## Implementation of PyStringObject
+## Implementation of PyBytesObject
 ## ================================
 ##
 ## The problem
@@ -29,15 +29,15 @@
 ## Solution
 ## --------
 ##
-## PyStringObject contains two additional members: the ob_size and a pointer to a
+## PyBytesObject contains two additional members: the ob_size and a pointer to a
 ## char ob_sval; it may be NULL.
 ##
-## - A string allocated by pypy will be converted into a PyStringObject with a
+## - A string allocated by pypy will be converted into a PyBytesObject with a
 ##   NULL buffer.  The first time PyString_AsString() is called, memory is
 ##   allocated (with flavor='raw') and content is copied.
 ##
 ## - A string allocated with PyString_FromStringAndSize(NULL, size) will
-##   allocate a PyStringObject structure, and a buffer with the specified
+##   allocate a PyBytesObject structure, and a buffer with the specified
 ##   size+1, but the reference won't be stored in the global map; there is no
 ##   corresponding object in pypy.  When from_ref() or Py_INCREF() is called,
 ##   the pypy string is created, and added to the global map of tracked
@@ -55,58 +55,58 @@
 ##   corresponds to the pypy gc-managed string.
 ##
 
-PyStringObjectStruct = lltype.ForwardReference()
-PyStringObject = lltype.Ptr(PyStringObjectStruct)
-PyStringObjectFields = PyVarObjectFields + \
+PyBytesObjectStruct = lltype.ForwardReference()
+PyBytesObject = lltype.Ptr(PyBytesObjectStruct)
+PyBytesObjectFields = PyVarObjectFields + \
     (("ob_shash", rffi.LONG), ("ob_sstate", rffi.INT), ("ob_sval", rffi.CArray(lltype.Char)))
-cpython_struct("PyStringObject", PyStringObjectFields, PyStringObjectStruct)
+cpython_struct("PyStringObject", PyBytesObjectFields, PyBytesObjectStruct)
 
 @bootstrap_function
-def init_stringobject(space):
-    "Type description of PyStringObject"
+def init_bytesobject(space):
+    "Type description of PyBytesObject"
     make_typedescr(space.w_str.layout.typedef,
-                   basestruct=PyStringObject.TO,
-                   attach=string_attach,
-                   dealloc=string_dealloc,
-                   realize=string_realize)
+                   basestruct=PyBytesObject.TO,
+                   attach=bytes_attach,
+                   dealloc=bytes_dealloc,
+                   realize=bytes_realize)
 
 PyString_Check, PyString_CheckExact = build_type_checkers("String", "w_str")
 
 def new_empty_str(space, length):
     """
-    Allocate a PyStringObject and its ob_sval, but without a corresponding
-    interpreter object.  The ob_sval may be mutated, until string_realize() is
+    Allocate a PyBytesObject and its ob_sval, but without a corresponding
+    interpreter object.  The ob_sval may be mutated, until bytes_realize() is
     called.  Refcount of the result is 1.
     """
     typedescr = get_typedescr(space.w_str.layout.typedef)
     py_obj = typedescr.allocate(space, space.w_str, length)
-    py_str = rffi.cast(PyStringObject, py_obj)
+    py_str = rffi.cast(PyBytesObject, py_obj)
     py_str.c_ob_shash = -1
     py_str.c_ob_sstate = rffi.cast(rffi.INT, 0) # SSTATE_NOT_INTERNED
     return py_str
 
-def string_attach(space, py_obj, w_obj):
+def bytes_attach(space, py_obj, w_obj):
     """
-    Copy RPython string object contents to a PyStringObject. The
+    Copy RPython string object contents to a PyBytesObject. The
     c_ob_sval must not be modified.
     """
-    py_str = rffi.cast(PyStringObject, py_obj)
+    py_str = rffi.cast(PyBytesObject, py_obj)
     s = space.str_w(w_obj)
     if py_str.c_ob_size  < len(s):
         raise oefmt(space.w_ValueError,
-            "string_attach called on object with ob_size %d but trying to store %d",
-            py_str.c_ob_size, len(s)) 
+            "bytes_attach called on object with ob_size %d but trying to store %d",
+            py_str.c_ob_size, len(s))
     rffi.c_memcpy(py_str.c_ob_sval, rffi.str2charp(s), len(s))
     py_str.c_ob_sval[len(s)] = '\0'
     py_str.c_ob_shash = space.hash_w(w_obj)
     py_str.c_ob_sstate = rffi.cast(rffi.INT, 1) # SSTATE_INTERNED_MORTAL
 
-def string_realize(space, py_obj):
+def bytes_realize(space, py_obj):
     """
-    Creates the string in the interpreter. The PyStringObject ob_sval must not
+    Creates the string in the interpreter. The PyBytesObject ob_sval must not
     be modified after this call.
     """
-    py_str = rffi.cast(PyStringObject, py_obj)
+    py_str = rffi.cast(PyBytesObject, py_obj)
     s = rffi.charpsize2str(py_str.c_ob_sval, py_str.c_ob_size)
     w_type = from_ref(space, rffi.cast(PyObject, py_obj.c_ob_type))
     w_obj = space.allocate_instance(W_BytesObject, w_type)
@@ -117,11 +117,11 @@
     return w_obj
 
 @cpython_api([PyObject], lltype.Void, header=None)
-def string_dealloc(space, py_obj):
-    """Frees allocated PyStringObject resources.
+def bytes_dealloc(space, py_obj):
+    """Frees allocated PyBytesObject resources.
     """
-    from pypy.module.cpyext.object import PyObject_dealloc
-    PyObject_dealloc(space, py_obj)
+    from pypy.module.cpyext.object import _dealloc
+    _dealloc(space, py_obj)
 
 #_______________________________________________________________________
 
@@ -154,10 +154,10 @@
             raise oefmt(space.w_TypeError,
                         "expected string or Unicode object, %T found",
                         from_ref(space, ref))
-    ref_str = rffi.cast(PyStringObject, ref)
+    ref_str = rffi.cast(PyBytesObject, ref)
     if not pyobj_has_w_obj(ref):
         # XXX Force the ref?
-        string_realize(space, ref)
+        bytes_realize(space, ref)
     return ref_str.c_ob_sval
 
 @cpython_api([rffi.VOIDP], rffi.CCHARP, error=0)
@@ -166,7 +166,7 @@
     # if no w_str is associated with this ref,
     # return the c-level ptr as RW
     if not pyobj_has_w_obj(ref):
-        py_str = rffi.cast(PyStringObject, ref)
+        py_str = rffi.cast(PyBytesObject, ref)
         return py_str.c_ob_sval
     return _PyString_AsString(space, ref)
 
@@ -183,8 +183,8 @@
                         from_ref(space, ref))
     if not pyobj_has_w_obj(ref):
         # force the ref
-        string_realize(space, ref)
-    ref_str = rffi.cast(PyStringObject, ref)
+        bytes_realize(space, ref)
+    ref_str = rffi.cast(PyBytesObject, ref)
     data[0] = ref_str.c_ob_sval
     if length:
         length[0] = ref_str.c_ob_size
@@ -200,7 +200,7 @@
 @cpython_api([PyObject], Py_ssize_t, error=-1)
 def PyString_Size(space, ref):
     if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_str:
-        ref = rffi.cast(PyStringObject, ref)
+        ref = rffi.cast(PyBytesObject, ref)
         return ref.c_ob_size
     else:
         w_obj = from_ref(space, ref)
@@ -222,7 +222,7 @@
     if pyobj_has_w_obj(ref[0]):
         raise oefmt(space.w_SystemError,
                     "_PyString_Resize called on already created string")
-    py_str = rffi.cast(PyStringObject, ref[0])
+    py_str = rffi.cast(PyBytesObject, ref[0])
     try:
         py_newstr = new_empty_str(space, newsize)
     except MemoryError:
diff --git a/pypy/module/cpyext/frameobject.py b/pypy/module/cpyext/frameobject.py
--- a/pypy/module/cpyext/frameobject.py
+++ b/pypy/module/cpyext/frameobject.py
@@ -46,8 +46,8 @@
     Py_DecRef(space, py_code)
     Py_DecRef(space, py_frame.c_f_globals)
     Py_DecRef(space, py_frame.c_f_locals)
-    from pypy.module.cpyext.object import PyObject_dealloc
-    PyObject_dealloc(space, py_obj)
+    from pypy.module.cpyext.object import _dealloc
+    _dealloc(space, py_obj)
 
 def frame_realize(space, py_obj):
     """
diff --git a/pypy/module/cpyext/funcobject.py b/pypy/module/cpyext/funcobject.py
--- a/pypy/module/cpyext/funcobject.py
+++ b/pypy/module/cpyext/funcobject.py
@@ -60,8 +60,8 @@
 def function_dealloc(space, py_obj):
     py_func = rffi.cast(PyFunctionObject, py_obj)
     Py_DecRef(space, py_func.c_func_name)
-    from pypy.module.cpyext.object import PyObject_dealloc
-    PyObject_dealloc(space, py_obj)
+    from pypy.module.cpyext.object import _dealloc
+    _dealloc(space, py_obj)
 
 def code_attach(space, py_obj, w_obj):
     py_code = rffi.cast(PyCodeObject, py_obj)
@@ -80,8 +80,8 @@
     py_code = rffi.cast(PyCodeObject, py_obj)
     Py_DecRef(space, py_code.c_co_name)
     Py_DecRef(space, py_code.c_co_filename)
-    from pypy.module.cpyext.object import PyObject_dealloc
-    PyObject_dealloc(space, py_obj)
+    from pypy.module.cpyext.object import _dealloc
+    _dealloc(space, py_obj)
 
 @cpython_api([PyObject], PyObject, result_borrowed=True)
 def PyFunction_GetCode(space, w_func):
diff --git a/pypy/module/cpyext/include/tupleobject.h b/pypy/module/cpyext/include/tupleobject.h
--- a/pypy/module/cpyext/include/tupleobject.h
+++ b/pypy/module/cpyext/include/tupleobject.h
@@ -8,9 +8,12 @@
 #endif
 
 typedef struct {
-    PyObject_HEAD
-    Py_ssize_t ob_size;
-    PyObject **ob_item;    /* XXX optimize to ob_item[] */
+    PyObject_VAR_HEAD
+    PyObject *ob_item[1];
+    /* ob_item contains space for 'ob_size' elements.
+     * Items must normally not be NULL, except during construction when
+     * the tuple is not yet visible outside the function that builds it.
+     */
 } PyTupleObject;
 
 /* defined in varargswrapper.c */
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
@@ -55,8 +55,8 @@
     py_func = rffi.cast(PyCFunctionObject, py_obj)
     Py_DecRef(space, py_func.c_m_self)
     Py_DecRef(space, py_func.c_m_module)
-    from pypy.module.cpyext.object import PyObject_dealloc
-    PyObject_dealloc(space, py_obj)
+    from pypy.module.cpyext.object import _dealloc
+    _dealloc(space, py_obj)
 
 
 class W_PyCFunctionObject(W_Root):
diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -54,6 +54,9 @@
 
 @cpython_api([PyObject], lltype.Void)
 def PyObject_dealloc(space, obj):
+    return _dealloc(space, obj)
+
+def _dealloc(space, obj):
     # This frees an object after its refcount dropped to zero, so we
     # assert that it is really zero here.
     assert obj.c_ob_refcnt == 0
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
@@ -164,7 +164,7 @@
     pytype = rffi.cast(PyTypeObjectPtr, as_pyobj(space, w_type))
     typedescr = get_typedescr(w_obj.typedef)
     if pytype.c_tp_itemsize != 0:
-        itemcount = space.len_w(w_obj) # PyStringObject and subclasses
+        itemcount = space.len_w(w_obj) # PyBytesObject and subclasses
     else:
         itemcount = 0
     py_obj = typedescr.allocate(space, w_type, itemcount=itemcount)
diff --git a/pypy/module/cpyext/pytraceback.py b/pypy/module/cpyext/pytraceback.py
--- a/pypy/module/cpyext/pytraceback.py
+++ b/pypy/module/cpyext/pytraceback.py
@@ -46,5 +46,5 @@
     py_traceback = rffi.cast(PyTracebackObject, py_obj)
     Py_DecRef(space, rffi.cast(PyObject, py_traceback.c_tb_next))
     Py_DecRef(space, rffi.cast(PyObject, py_traceback.c_tb_frame))
-    from pypy.module.cpyext.object import PyObject_dealloc
-    PyObject_dealloc(space, py_obj)
+    from pypy.module.cpyext.object import _dealloc
+    _dealloc(space, py_obj)
diff --git a/pypy/module/cpyext/sliceobject.py b/pypy/module/cpyext/sliceobject.py
--- a/pypy/module/cpyext/sliceobject.py
+++ b/pypy/module/cpyext/sliceobject.py
@@ -38,14 +38,14 @@
 
 @cpython_api([PyObject], lltype.Void, header=None)
 def slice_dealloc(space, py_obj):
-    """Frees allocated PyStringObject resources.
+    """Frees allocated PyBytesObject resources.
     """
     py_slice = rffi.cast(PySliceObject, py_obj)
     Py_DecRef(space, py_slice.c_start)
     Py_DecRef(space, py_slice.c_stop)
     Py_DecRef(space, py_slice.c_step)
-    from pypy.module.cpyext.object import PyObject_dealloc
-    PyObject_dealloc(space, py_obj)
+    from pypy.module.cpyext.object import _dealloc
+    _dealloc(space, py_obj)
 
 PySlice_Check, PySlice_CheckExact = build_type_checkers("Slice")
 
@@ -73,7 +73,7 @@
     length length, and store the length of the slice in slicelength.  Out
     of bounds indices are clipped in a manner consistent with the handling of
     normal slices.
-    
+
     Returns 0 on success and -1 on error with exception set."""
     if not PySlice_Check(space, w_slice):
         PyErr_BadInternalCall(space)
@@ -88,11 +88,11 @@
     """Retrieve the start, stop and step indices from the slice object slice,
     assuming a sequence of length length. Treats indices greater than
     length as errors.
-    
+
     Returns 0 on success and -1 on error with no exception set (unless one of
     the indices was not None and failed to be converted to an integer,
     in which case -1 is returned with an exception set).
-    
+
     You probably do not want to use this function.  If you want to use slice
     objects in versions of Python prior to 2.3, you would probably do well to
     incorporate the source of PySlice_GetIndicesEx(), suitably renamed,
diff --git a/pypy/module/cpyext/test/array.c b/pypy/module/cpyext/test/array.c
--- a/pypy/module/cpyext/test/array.c
+++ b/pypy/module/cpyext/test/array.c
@@ -1858,6 +1858,56 @@
     }
 }
 
+static PyObject*
+array_multiply(PyObject* obj1, PyObject* obj2)
+{
+    if (PyList_Check(obj1) && ((arrayobject*)obj2)->ob_descr->typecode == 'i' && Py_SIZE(obj2) == 1)
+    {
+        int ii, nn;
+        int n = PyList_Size(obj1);
+        PyObject *v = getarrayitem(obj2, 0);
+        int i = ((PyIntObject*)v)->ob_ival;
+        PyObject * ret = PyList_New(n*i);
+        for (ii = 0; ii < i; ii++)
+            for (nn = 0; nn < n; nn++)
+            {
+                v = PyList_GetItem(obj1, nn);
+                PyList_SetItem(ret, nn+ii*n, v);
+            }
+        return ret;
+    }
+    else if (PyList_Check(obj2) && ((arrayobject*)obj1)->ob_descr->typecode == 'i' && Py_SIZE(obj1) == 1)
+    {
+        int ii, nn;
+        int n = PyList_Size(obj2);
+        PyObject *v = getarrayitem(obj1, 0);
+        int i = ((PyIntObject*)v)->ob_ival;
+        PyObject * ret = PyList_New(n*i);
+        for (ii = 0; ii < i; ii++)
+            for (nn = 0; nn < n; nn++)
+            {
+                v = PyList_GetItem(obj2, nn);
+                PyList_SetItem(ret, nn+ii*n, v);
+            }
+        return ret;
+    }
+    else if(obj1->ob_type == &Arraytype)
+        fprintf(stderr, "\nCannot multiply array of type %c and %s\n",
+            ((arrayobject*)obj1)->ob_descr->typecode, obj2->ob_type->tp_name); 
+    else if(obj2->ob_type == &Arraytype)
+        fprintf(stderr, "\nCannot multiply array of type %c and %s\n",
+            ((arrayobject*)obj2)->ob_descr->typecode, obj1->ob_type->tp_name); 
+    Py_INCREF(Py_NotImplemented);
+    return Py_NotImplemented;
+}
+
+static PyNumberMethods array_as_number = {
+    (binaryfunc)NULL, /* nb_add*/
+    (binaryfunc)NULL, /* nb_subtract */
+    (binaryfunc)array_multiply, /* nb_multiply */
+    (binaryfunc)NULL, /* nb_divide */
+};
+
 static PyMappingMethods array_as_mapping = {
     (lenfunc)array_length,
     (binaryfunc)array_subscr,
@@ -2117,7 +2167,7 @@
     0,                                          /* tp_setattr */
     0,                                          /* tp_compare */
     (reprfunc)array_repr,                       /* tp_repr */
-    0,                                          /* tp_as_number*/
+    &array_as_number,                           /* tp_as_number*/
     &array_as_sequence,                         /* tp_as_sequence*/
     &array_as_mapping,                          /* tp_as_mapping*/
     0,                                          /* tp_hash */
@@ -2126,7 +2176,8 @@
     PyObject_GenericGetAttr,                    /* tp_getattro */
     0,                                          /* tp_setattro */
     &array_as_buffer,                           /* tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS,  /* tp_flags */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | 
+    Py_TPFLAGS_HAVE_WEAKREFS | Py_TPFLAGS_CHECKTYPES,  /* tp_flags */
     arraytype_doc,                              /* tp_doc */
     0,                                          /* tp_traverse */
     0,                                          /* tp_clear */
diff --git a/pypy/module/cpyext/test/foo.c b/pypy/module/cpyext/test/foo.c
--- a/pypy/module/cpyext/test/foo.c
+++ b/pypy/module/cpyext/test/foo.c
@@ -1,6 +1,20 @@
 #include "Python.h"
 #include "structmember.h"
 
+#if PY_MAJOR_VERSION >= 3
+    #define PyInt_FromLong PyLong_FromLong
+    #define PyInt_AsLong PyLong_AsLong
+    #define PyThing_FromStringAndSize PyUnicode_FromStringAndSize
+    #define PyThing_FromString PyUnicode_FromString
+    #define PyThing_Check PyUnicode_Check
+    #define _PyThing_AsString _PyUnicode_AsString
+#else
+    #define PyThing_FromStringAndSize PyString_FromStringAndSize
+    #define PyThing_FromString PyString_FromString
+    #define PyThing_Check PyString_Check
+    #define _PyThing_AsString PyString_AsString
+#endif
+
 typedef struct {
     PyObject_HEAD
     int    foo;        /* the context holder */
@@ -88,7 +102,7 @@
 static PyObject *
 foo_get_name(PyObject *self, void *closure)
 {
-    return PyString_FromStringAndSize("Foo Example", 11);
+    return PyThing_FromStringAndSize("Foo Example", 11);
 }
 
 static PyObject *
@@ -114,7 +128,7 @@
 {
     PyObject *format;
 
-    format = PyString_FromString("<Foo>");
+    format = PyThing_FromString("<Foo>");
     if (format == NULL) return NULL;
     return format;
 }
@@ -130,11 +144,11 @@
 foo_setattro(fooobject *self, PyObject *name, PyObject *value)
 {
     char *name_str;
-    if (!PyString_Check(name)) {
+    if (!PyThing_Check(name)) {
         PyErr_SetObject(PyExc_AttributeError, name);
         return -1;
     }
-    name_str = PyString_AsString(name);
+    name_str = _PyThing_AsString(name);
     if (strcmp(name_str, "set_foo") == 0)
     {
         long v = PyInt_AsLong(value);
@@ -620,20 +634,65 @@
     (destructor)custom_dealloc, /*tp_dealloc*/
 };
 
+static PyTypeObject TupleLike = {
+    PyObject_HEAD_INIT(NULL)
+    0,
+    "foo.TupleLike",         /*tp_name*/
+    sizeof(PyObject),        /*tp_size*/
+};
+
+
 static PyObject *size_of_instances(PyObject *self, PyObject *t)
 {
     return PyInt_FromLong(((PyTypeObject *)t)->tp_basicsize);
 }
 
+
+static PyObject * is_TupleLike(PyObject *self, PyObject * t)
+{
+    int tf = t->ob_type == &TupleLike;
+    if (t->ob_type->tp_itemsize == 0)
+        return PyInt_FromLong(-1);
+    return PyInt_FromLong(tf);
+}
+
 /* List of functions exported by this module */
 
 static PyMethodDef foo_functions[] = {
     {"new",        (PyCFunction)foo_new, METH_NOARGS, NULL},
     {"newCustom",  (PyCFunction)newCustom, METH_NOARGS, NULL},
     {"size_of_instances", (PyCFunction)size_of_instances, METH_O, NULL},
+    {"is_TupleLike", (PyCFunction)is_TupleLike, METH_O, NULL},
     {NULL,        NULL}    /* Sentinel */
 };
 
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef moduledef = {
+    PyModuleDef_HEAD_INIT,
+    "foo",
+    "Module Doc",
+    -1,
+    foo_functions, 
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+};
+#define INITERROR return NULL
+
+/* Initialize this module. */
+#ifdef __GNUC__
+extern __attribute__((visibility("default")))
+#else
+extern __declspec(dllexport)
+#endif
+
+PyMODINIT_FUNC
+PyInit_foo(void)
+
+#else
+
+#define INITERROR return
 
 /* Initialize this module. */
 #ifdef __GNUC__
@@ -644,8 +703,16 @@
 
 PyMODINIT_FUNC
 initfoo(void)
+#endif
 {
-    PyObject *m, *d;
+    PyObject *d;
+#if PY_MAJOR_VERSION >= 3
+    PyObject *module = PyModule_Create(&moduledef);
+#else
+    PyObject *module = Py_InitModule("foo", foo_functions);
+#endif
+    if (module == NULL)
+        INITERROR;
 
     footype.tp_new = PyType_GenericNew;
 
@@ -654,52 +721,59 @@
     MetaType.tp_base = &PyType_Type;
 
     if (PyType_Ready(&footype) < 0)
-        return;
+        INITERROR;
     if (PyType_Ready(&UnicodeSubtype) < 0)
-        return;
+        INITERROR;
     if (PyType_Ready(&UnicodeSubtype2) < 0)
-        return;
+        INITERROR;
     if (PyType_Ready(&MetaType) < 0)
-        return;
+        INITERROR;
     if (PyType_Ready(&InitErrType) < 0)
-        return;
+        INITERROR;
     if (PyType_Ready(&SimplePropertyType) < 0)
-        return;
+        INITERROR;
 
     SimplePropertyType.tp_new = PyType_GenericNew;
     InitErrType.tp_new = PyType_GenericNew;
 
     CustomType.ob_type = &MetaType;
     if (PyType_Ready(&CustomType) < 0)
-        return;
+        INITERROR;
 
     UnicodeSubtype3.tp_flags = Py_TPFLAGS_DEFAULT;
     UnicodeSubtype3.tp_base = &UnicodeSubtype;
     UnicodeSubtype3.tp_bases = Py_BuildValue("(OO)", &UnicodeSubtype,
                                                     &CustomType);
     if (PyType_Ready(&UnicodeSubtype3) < 0)
-        return;
+        INITERROR;
 
-    m = Py_InitModule("foo", foo_functions);
-    if (m == NULL)
-        return;
-    d = PyModule_GetDict(m);
+    TupleLike.tp_base = &PyTuple_Type;
+    if (PyType_Ready(&TupleLike) < 0)
+        INITERROR;
+
+
+    d = PyModule_GetDict(module);
     if (d == NULL)
-        return;
+        INITERROR;
     if (PyDict_SetItemString(d, "fooType", (PyObject *)&footype) < 0)
-        return;
+        INITERROR;
     if (PyDict_SetItemString(d, "UnicodeSubtype", (PyObject *) &UnicodeSubtype) < 0)
-        return;
+        INITERROR;
     if (PyDict_SetItemString(d, "UnicodeSubtype2", (PyObject *) &UnicodeSubtype2) < 0)
-        return;
+        INITERROR;
     if (PyDict_SetItemString(d, "UnicodeSubtype3", (PyObject *) &UnicodeSubtype3) < 0)
-        return;
+        INITERROR;
     if (PyDict_SetItemString(d, "MetaType", (PyObject *) &MetaType) < 0)
-        return;
+        INITERROR;
     if (PyDict_SetItemString(d, "InitErrType", (PyObject *) &InitErrType) < 0)
-        return;
+        INITERROR;
     if (PyDict_SetItemString(d, "Property", (PyObject *) &SimplePropertyType) < 0)
-        return;
+        INITERROR;
     if (PyDict_SetItemString(d, "Custom", (PyObject *) &CustomType) < 0)
-        return;
+        INITERROR;
+    if (PyDict_SetItemString(d, "TupleLike", (PyObject *) &TupleLike) < 0)
+        INITERROR;
+#if PY_MAJOR_VERSION >=3
+    return module;
+#endif
 }
diff --git a/pypy/module/cpyext/test/test_arraymodule.py b/pypy/module/cpyext/test/test_arraymodule.py
--- a/pypy/module/cpyext/test/test_arraymodule.py
+++ b/pypy/module/cpyext/test/test_arraymodule.py
@@ -77,3 +77,10 @@
         #assert s == "carray\n_reconstruct\np0\n(S'i'\np1\n(lp2\nI1\naI2\naI3\naI4\natp3\nRp4\n."
         rra = pickle.loads(s) # rra is arr backwards
         #assert arr.tolist() == rra.tolist()
+
+    def test_binop_mul_impl(self):
+        # check that rmul is called
+        module = self.import_module(name='array')
+        arr = module.array('i', [2])
+        res = [1, 2, 3] * arr
+        assert res == [1, 2, 3, 1, 2, 3]
diff --git a/pypy/module/cpyext/test/test_bytearrayobject.py b/pypy/module/cpyext/test/test_bytearrayobject.py
--- a/pypy/module/cpyext/test/test_bytearrayobject.py
+++ b/pypy/module/cpyext/test/test_bytearrayobject.py
@@ -28,10 +28,10 @@
              """
                 return PyBool_FromLong(PyByteArray_Check(PyTuple_GetItem(args, 0)));
              """)], prologue='#include <stdlib.h>')
-        assert module.get_hello1() == 'Hello world'
-        assert module.get_hello2() == 'Hello world\x00'
+        assert module.get_hello1() == b'Hello world'
+        assert module.get_hello2() == b'Hello world\x00'
         assert module.test_Size()
-        assert module.test_is_bytearray(bytearray(""))
+        assert module.test_is_bytearray(bytearray(b""))
         assert not module.test_is_bytearray(())
 
     def test_bytearray_buffer_init(self):
@@ -63,7 +63,7 @@
             ])
         s = module.getbytearray()
         assert len(s) == 4
-        assert s == 'ab\x00c'
+        assert s == b'ab\x00c'
 
     def test_bytearray_mutable(self):
         module = self.import_extension('foo', [
@@ -79,9 +79,9 @@
              """),
             ])
         s = module.mutable()
-        if s == '\x00' * 10:
+        if s == b'\x00' * 10:
             assert False, "no RW access to bytearray"
-        assert s[:6] == 'works\x00'
+        assert s[:6] == b'works\x00'
 
     def test_AsByteArray(self):
         module = self.import_extension('foo', [
@@ -97,18 +97,18 @@
              """),
             ])
         s = module.getbytearray()
-        assert s == 'test'
+        assert s == b'test'
 
     def test_manipulations(self):
         import sys
         module = self.import_extension('foo', [
-            ("bytearray_from_string", "METH_VARARGS",
+            ("bytearray_from_bytes", "METH_VARARGS",
              '''
-             return PyByteArray_FromStringAndSize(PyString_AsString(
+             return PyByteArray_FromStringAndSize(PyBytes_AsString(
                        PyTuple_GetItem(args, 0)), 4);
              '''
             ),
-            ("str_from_bytearray", "METH_VARARGS",
+            ("bytes_from_bytearray", "METH_VARARGS",
              '''
                 char * buf;
                 int n;
@@ -121,7 +121,7 @@
                     return NULL;
                 }
                 n = PyByteArray_Size(obj);
-                return PyString_FromStringAndSize(buf, n);
+                return PyBytes_FromStringAndSize(buf, n);
              '''
             ),
             ("concat", "METH_VARARGS",
@@ -129,7 +129,7 @@
                 PyObject * ret, *right, *left;
                 PyObject *ba1, *ba2;
                 if (!PyArg_ParseTuple(args, "OO", &left, &right)) {
-                    return PyString_FromString("parse failed");
+                    return PyUnicode_FromString("parse failed");
                 }
                 ba1 = PyByteArray_FromObject(left);
                 ba2 = PyByteArray_FromObject(right);
@@ -141,16 +141,16 @@
                 ret = PyByteArray_Concat(ba1, ba2);
                 return ret;
              """)])
-        assert module.bytearray_from_string("huheduwe") == "huhe"
-        assert module.str_from_bytearray(bytearray('abc')) == 'abc'
+        assert module.bytearray_from_bytes(b"huheduwe") == b"huhe"
+        assert module.bytes_from_bytearray(bytearray(b'abc')) == b'abc'
         if '__pypy__' in sys.builtin_module_names:
             # CPython only makes an assert.
-            raises(ValueError, module.str_from_bytearray, 4.0)
-        ret = module.concat('abc', 'def')
-        assert ret == 'abcdef'
+            raises(ValueError, module.bytes_from_bytearray, 4.0)
+        ret = module.concat(b'abc', b'def')
+        assert ret == b'abcdef'
         assert not isinstance(ret, str)
         assert isinstance(ret, bytearray)
-        raises(TypeError, module.concat, 'abc', u'def')
+        raises(TypeError, module.concat, b'abc', u'def')
 
     def test_bytearray_resize(self):
         module = self.import_extension('foo', [
@@ -159,7 +159,7 @@
              PyObject *obj, *ba;
              int newsize, oldsize, ret;
              if (!PyArg_ParseTuple(args, "Oi", &obj, &newsize)) {
-                 return PyString_FromString("parse failed");
+                 return PyUnicode_FromString("parse failed");
              }
 
              ba = PyByteArray_FromObject(obj);
@@ -168,7 +168,7 @@
              oldsize = PyByteArray_Size(ba);
              if (oldsize == 0)
              {
-                  return PyString_FromString("oldsize is 0");
+                  return PyUnicode_FromString("oldsize is 0");
              }
              ret = PyByteArray_Resize(ba, newsize);
              if (ret != 0)
@@ -179,10 +179,9 @@
              return ba;
              '''
             )])
-        ret = module.bytearray_resize('abc', 6)
+        ret = module.bytearray_resize(b'abc', 6)
         assert len(ret) == 6,"%s, len=%d" % (ret, len(ret))
-        assert ret == 'abc\x00\x00\x00'
-        ret = module.bytearray_resize('abcdefghi', 4)
+        assert ret == b'abc\x00\x00\x00'
+        ret = module.bytearray_resize(b'abcdefghi', 4)
         assert len(ret) == 4,"%s, len=%d" % (ret, len(ret))
-        assert ret == 'abcd'
-
+        assert ret == b'abcd'
diff --git a/pypy/module/cpyext/test/test_bytesobject.py b/pypy/module/cpyext/test/test_bytesobject.py
--- a/pypy/module/cpyext/test/test_bytesobject.py
+++ b/pypy/module/cpyext/test/test_bytesobject.py
@@ -2,7 +2,7 @@
 from rpython.rtyper.lltypesystem import rffi, lltype
 from pypy.module.cpyext.test.test_api import BaseApiTest
 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
-from pypy.module.cpyext.bytesobject import new_empty_str, PyStringObject
+from pypy.module.cpyext.bytesobject import new_empty_str, PyBytesObject
 from pypy.module.cpyext.api import PyObjectP, PyObject, Py_ssize_tP, generic_cpy_call
 from pypy.module.cpyext.pyobject import Py_DecRef, from_ref, make_ref
 from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr
@@ -10,22 +10,22 @@
 import py
 import sys
 
-class AppTestStringObject(AppTestCpythonExtensionBase):
-    def test_stringobject(self):
+class AppTestBytesObject(AppTestCpythonExtensionBase):
+    def test_bytesobject(self):
         module = self.import_extension('foo', [
             ("get_hello1", "METH_NOARGS",
              """
-                 return PyString_FromStringAndSize(
+                 return PyBytes_FromStringAndSize(
                      "Hello world<should not be included>", 11);
              """),
             ("get_hello2", "METH_NOARGS",
              """
-                 return PyString_FromString("Hello world");
+                 return PyBytes_FromString("Hello world");
              """),
             ("test_Size", "METH_NOARGS",
              """
-                 PyObject* s = PyString_FromString("Hello world");
-                 int result = PyString_Size(s);
+                 PyObject* s = PyBytes_FromString("Hello world");
+                 int result = PyBytes_Size(s);
 
                  Py_DECREF(s);
                  return PyLong_FromLong(result);
@@ -33,38 +33,38 @@
             ("test_Size_exception", "METH_NOARGS",
              """
                  PyObject* f = PyFloat_FromDouble(1.0);
-                 PyString_Size(f);
+                 PyBytes_Size(f);
 
                  Py_DECREF(f);
                  return NULL;
              """),
-             ("test_is_string", "METH_VARARGS",
+             ("test_is_bytes", "METH_VARARGS",
              """
-                return PyBool_FromLong(PyString_Check(PyTuple_GetItem(args, 0)));
+                return PyBool_FromLong(PyBytes_Check(PyTuple_GetItem(args, 0)));
              """)], prologue='#include <stdlib.h>')
-        assert module.get_hello1() == 'Hello world'
-        assert module.get_hello2() == 'Hello world'
+        assert module.get_hello1() == b'Hello world'
+        assert module.get_hello2() == b'Hello world'
         assert module.test_Size() == 11
         raises(TypeError, module.test_Size_exception)
 
-        assert module.test_is_string("")
-        assert not module.test_is_string(())
+        assert module.test_is_bytes(b"")
+        assert not module.test_is_bytes(())
 
-    def test_string_buffer_init(self):
+    def test_bytes_buffer_init(self):
         module = self.import_extension('foo', [
-            ("getstring", "METH_NOARGS",
+            ("getbytes", "METH_NOARGS",
              """
                  PyObject *s, *t;
                  char* c;
 
-                 s = PyString_FromStringAndSize(NULL, 4);
+                 s = PyBytes_FromStringAndSize(NULL, 4);
                  if (s == NULL)
                     return NULL;
-                 t = PyString_FromStringAndSize(NULL, 3);
+                 t = PyBytes_FromStringAndSize(NULL, 3);
                  if (t == NULL)
                     return NULL;
                  Py_DECREF(t);
-                 c = PyString_AS_STRING(s);
+                 c = PyBytes_AS_STRING(s);
                  c[0] = 'a';
                  c[1] = 'b';
                  c[2] = 0;
@@ -72,62 +72,62 @@
                  return s;
              """),
             ])
-        s = module.getstring()
+        s = module.getbytes()
         assert len(s) == 4
-        assert s == 'ab\x00c'
+        assert s == b'ab\x00c'
 
-    def test_string_tp_alloc(self):
+    def test_bytes_tp_alloc(self):
         module = self.import_extension('foo', [
             ("tpalloc", "METH_NOARGS",
              """
                 PyObject *base;
                 PyTypeObject * type;
-                PyStringObject *obj;
-                base = PyString_FromString("test");
-                if (PyString_GET_SIZE(base) != 4)
-                    return PyLong_FromLong(-PyString_GET_SIZE(base));
+                PyBytesObject *obj;
+                base = PyBytes_FromString("test");
+                if (PyBytes_GET_SIZE(base) != 4)
+                    return PyLong_FromLong(-PyBytes_GET_SIZE(base));
                 type = base->ob_type;
                 if (type->tp_itemsize != 1)
                     return PyLong_FromLong(type->tp_itemsize);
-                obj = (PyStringObject*)type->tp_alloc(type, 10);
-                if (PyString_GET_SIZE(obj) != 10)
-                    return PyLong_FromLong(PyString_GET_SIZE(obj));
-                /* cannot work, there is only RO access */
-                memcpy(PyString_AS_STRING(obj), "works", 6);
+                obj = (PyBytesObject*)type->tp_alloc(type, 10);
+                if (PyBytes_GET_SIZE(obj) != 10)
+                    return PyLong_FromLong(PyBytes_GET_SIZE(obj));
+                /* cannot work, there is only RO access
+                memcpy(PyBytes_AS_STRING(obj), "works", 6); */
                 Py_INCREF(obj);
                 return (PyObject*)obj;
              """),
             ('alloc_rw', "METH_NOARGS",
              '''
-                PyObject *obj = _PyObject_NewVar(&PyString_Type, 10);
-                memcpy(PyString_AS_STRING(obj), "works", 6);
+                PyObject *obj = _PyObject_NewVar(&PyBytes_Type, 10);
+                memcpy(PyBytes_AS_STRING(obj), "works", 6);
                 return (PyObject*)obj;
              '''),
             ])
         s = module.alloc_rw()
-        assert s == 'works' + '\x00' * 5
+        assert s == b'works' + b'\x00' * 5
         s = module.tpalloc()
-        assert s == 'works' + '\x00' * 5
+        assert s == b'\x00' * 10
 
     def test_AsString(self):
         module = self.import_extension('foo', [
-            ("getstring", "METH_NOARGS",
+            ("getbytes", "METH_NOARGS",
              """
-                 PyObject* s1 = PyString_FromStringAndSize("test", 4);
-                 char* c = PyString_AsString(s1);
-                 PyObject* s2 = PyString_FromStringAndSize(c, 4);
+                 PyObject* s1 = PyBytes_FromStringAndSize("test", 4);
+                 char* c = PyBytes_AsString(s1);
+                 PyObject* s2 = PyBytes_FromStringAndSize(c, 4);
                  Py_DECREF(s1);
                  return s2;
              """),
             ])
-        s = module.getstring()
-        assert s == 'test'
+        s = module.getbytes()
+        assert s == b'test'
 
     def test_manipulations(self):
         module = self.import_extension('foo', [
-            ("string_as_string", "METH_VARARGS",
+            ("bytes_as_string", "METH_VARARGS",
              '''
-             return PyString_FromStringAndSize(PyString_AsString(
+             return PyBytes_FromStringAndSize(PyBytes_AsString(
                        PyTuple_GetItem(args, 0)), 4);
              '''
             ),
@@ -137,22 +137,22 @@
                 PyObject * left = PyTuple_GetItem(args, 0);
                 Py_INCREF(left);    /* the reference will be stolen! */
                 v = &left;
-                PyString_Concat(v, PyTuple_GetItem(args, 1));
+                PyBytes_Concat(v, PyTuple_GetItem(args, 1));
                 return *v;
              """)])
-        assert module.string_as_string("huheduwe") == "huhe"
-        ret = module.concat('abc', 'def')
-        assert ret == 'abcdef'
+        assert module.bytes_as_string(b"huheduwe") == b"huhe"
+        ret = module.concat(b'abc', b'def')
+        assert ret == b'abcdef'
         ret = module.concat('abc', u'def')
         assert not isinstance(ret, str)
         assert isinstance(ret, unicode)
         assert ret == 'abcdef'
 
-    def test_py_string_as_string_None(self):
+    def test_py_bytes_as_string_None(self):
         module = self.import_extension('foo', [
             ("string_None", "METH_VARARGS",
              '''
-             if (PyString_AsString(Py_None)) {
+             if (PyBytes_AsString(Py_None)) {
                 Py_RETURN_NONE;
              }
              return NULL;
@@ -162,18 +162,18 @@
 
     def test_AsStringAndSize(self):
         module = self.import_extension('foo', [
-            ("getstring", "METH_NOARGS",
+            ("getbytes", "METH_NOARGS",
              """
-                 PyObject* s1 = PyString_FromStringAndSize("te\\0st", 5);
+                 PyObject* s1 = PyBytes_FromStringAndSize("te\\0st", 5);
                  char *buf;
                  Py_ssize_t len;
-                 if (PyString_AsStringAndSize(s1, &buf, &len) < 0)
+                 if (PyBytes_AsStringAndSize(s1, &buf, &len) < 0)
                      return NULL;
                  if (len != 5) {
                      PyErr_SetString(PyExc_AssertionError, "Bad Length");
                      return NULL;
                  }
-                 if (PyString_AsStringAndSize(s1, &buf, NULL) >= 0) {
+                 if (PyBytes_AsStringAndSize(s1, &buf, NULL) >= 0) {
                      PyErr_SetString(PyExc_AssertionError, "Should Have failed");
                      return NULL;
                  }
@@ -183,7 +183,7 @@
                  return Py_None;
              """),
             ])
-        module.getstring()
+        module.getbytes()
 
     def test_py_string_as_string_Unicode(self):
         module = self.import_extension('foo', [
@@ -266,7 +266,7 @@
                  PyObject *s = args;
                  Py_INCREF(s);
                  PyString_InternInPlace(&s);
-                 if (((PyStringObject*)s)->ob_sstate == SSTATE_NOT_INTERNED)
+                 if (((PyBytesObject*)s)->ob_sstate == SSTATE_NOT_INTERNED)
                  {
                     Py_DECREF(s);
                     s = PyString_FromString("interned error");
@@ -284,7 +284,7 @@
              ("test_macro_invocations", "METH_NOARGS",
              """
                 PyObject* o = PyString_FromString("");
-                PyStringObject* u = (PyStringObject*)o;
+                PyBytesObject* u = (PyBytesObject*)o;
 
                 PyString_GET_SIZE(u);
                 PyString_GET_SIZE(o);
@@ -301,17 +301,17 @@
             ("test_hash", "METH_VARARGS",
              '''
                 PyObject* obj = (PyTuple_GetItem(args, 0));
-                long hash = ((PyStringObject*)obj)->ob_shash;
+                long hash = ((PyBytesObject*)obj)->ob_shash;
                 return PyLong_FromLong(hash);
              '''
              ),
             ("test_sstate", "METH_NOARGS",
              '''
                 PyObject *s = PyString_FromString("xyz");
-                /*int sstate = ((PyStringObject*)s)->ob_sstate;
+                /*int sstate = ((PyBytesObject*)s)->ob_sstate;
                 printf("sstate now %d\\n", sstate);*/
                 PyString_InternInPlace(&s);
-                /*sstate = ((PyStringObject*)s)->ob_sstate;
+                /*sstate = ((PyBytesObject*)s)->ob_sstate;
                 printf("sstate now %d\\n", sstate);*/
                 Py_DECREF(s);
                 return PyBool_FromLong(1);
@@ -345,7 +345,7 @@
                     PyObject_HEAD_INIT(NULL)
                     0,                            /* ob_size */
                     "bar.string_",                /* tp_name*/
-                    sizeof(PyStringObject), /* tp_basicsize*/
+                    sizeof(PyBytesObject), /* tp_basicsize*/
                     0                             /* tp_itemsize */
                     };
 
@@ -401,7 +401,7 @@
                             return NULL;
                         }
                         destptr = PyString_AS_STRING(obj);
-                        ((PyStringObject *)obj)->ob_shash = -1;
+                        ((PyBytesObject *)obj)->ob_shash = -1;
                         memcpy(destptr, data, itemsize);
                         return obj;
                     }
@@ -420,8 +420,8 @@
         assert type(a).__name__ == 'string_'
         assert a == 'abc'
 
-class TestString(BaseApiTest):
-    def test_string_resize(self, space, api):
+class TestBytes(BaseApiTest):
+    def test_bytes_resize(self, space, api):
         py_str = new_empty_str(space, 10)
         ar = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
         py_str.c_ob_sval[0] = 'a'
@@ -429,14 +429,14 @@
         py_str.c_ob_sval[2] = 'c'
         ar[0] = rffi.cast(PyObject, py_str)
         api._PyString_Resize(ar, 3)
-        py_str = rffi.cast(PyStringObject, ar[0])
+        py_str = rffi.cast(PyBytesObject, ar[0])
         assert py_str.c_ob_size == 3
         assert py_str.c_ob_sval[1] == 'b'
         assert py_str.c_ob_sval[3] == '\x00'
         # the same for growing
         ar[0] = rffi.cast(PyObject, py_str)
         api._PyString_Resize(ar, 10)
-        py_str = rffi.cast(PyStringObject, ar[0])
+        py_str = rffi.cast(PyBytesObject, ar[0])
         assert py_str.c_ob_size == 10
         assert py_str.c_ob_sval[1] == 'b'
         assert py_str.c_ob_sval[10] == '\x00'
diff --git a/pypy/module/cpyext/test/test_tupleobject.py b/pypy/module/cpyext/test/test_tupleobject.py
--- a/pypy/module/cpyext/test/test_tupleobject.py
+++ b/pypy/module/cpyext/test/test_tupleobject.py
@@ -51,7 +51,7 @@
         api._PyTuple_Resize(ar, 10)
         assert api.PyTuple_Size(ar[0]) == 10
         for i in range(3, 10):
-            rffi.cast(PyTupleObject, py_tuple).c_ob_item[i] = make_ref(
+            rffi.cast(PyTupleObject, ar[0]).c_ob_item[i] = make_ref(
                 space, space.wrap(42 + i))
         w_tuple = from_ref(space, ar[0])
         assert space.int_w(space.len(w_tuple)) == 10
@@ -151,3 +151,8 @@
              """),
             ])
         module.run()
+
+    def test_tuple_subclass(self):
+        module = self.import_module(name='foo')
+        a = module.TupleLike([1, 2, 3])
+        assert module.is_TupleLike(a) == 1
diff --git a/pypy/module/cpyext/tupleobject.py b/pypy/module/cpyext/tupleobject.py
--- a/pypy/module/cpyext/tupleobject.py
+++ b/pypy/module/cpyext/tupleobject.py
@@ -2,10 +2,10 @@
 from rpython.rtyper.lltypesystem import rffi, lltype
 from rpython.rlib.debug import fatalerror_notb
 from pypy.module.cpyext.api import (cpython_api, Py_ssize_t, CANNOT_FAIL,
-                                    build_type_checkers, PyObjectFields,
+                                    build_type_checkers, PyVarObjectFields,
                                     cpython_struct, bootstrap_function)
 from pypy.module.cpyext.pyobject import (PyObject, PyObjectP, Py_DecRef,
-    make_ref, from_ref, decref,
+    make_ref, from_ref, decref, incref, pyobj_has_w_obj,
     track_reference, make_typedescr, get_typedescr)
 from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
 from pypy.objspace.std.tupleobject import W_TupleObject
@@ -29,8 +29,8 @@
 PyTupleObjectStruct = lltype.ForwardReference()
 PyTupleObject = lltype.Ptr(PyTupleObjectStruct)
 ObjectItems = rffi.CArray(PyObject)
-PyTupleObjectFields = PyObjectFields + \
-    (("ob_size", Py_ssize_t), ("ob_item", lltype.Ptr(ObjectItems)))
+PyTupleObjectFields = PyVarObjectFields + \
+    (("ob_item", ObjectItems),)
 cpython_struct("PyTupleObject", PyTupleObjectFields, PyTupleObjectStruct)
 
 @bootstrap_function
@@ -56,14 +56,12 @@
     tuple_realize() is called.  Refcount of the result is 1.
     """
     typedescr = get_typedescr(space.w_tuple.layout.typedef)
-    py_obj = typedescr.allocate(space, space.w_tuple)
+    py_obj = typedescr.allocate(space, space.w_tuple, length)
     py_tup = rffi.cast(PyTupleObject, py_obj)
-
-    py_tup.c_ob_item = lltype.malloc(ObjectItems, length,
-                                     flavor='raw', zero=True,
-                                     add_memory_pressure=True)
-    py_tup.c_ob_size = length
-    return py_tup
+    p = py_tup.c_ob_item
+    for i in range(py_tup.c_ob_size):
+        p[i] = lltype.nullptr(PyObject.TO)
+    return py_obj
 
 def tuple_attach(space, py_obj, w_obj):
     """
@@ -71,23 +69,24 @@
     buffer must not be modified.
     """
     items_w = space.fixedview(w_obj)
-    l = len(items_w)
-    p = lltype.malloc(ObjectItems, l, flavor='raw',
-                      add_memory_pressure=True)
+    py_tup = rffi.cast(PyTupleObject, py_obj)
+    length = len(items_w)
+    if py_tup.c_ob_size < length:
+        raise oefmt(space.w_ValueError,
+            "tuple_attach called on object with ob_size %d but trying to store %d",
+            py_tup.c_ob_size, length) 
     i = 0
     try:
-        while i < l:
-            p[i] = make_ref(space, items_w[i])
+        while i < length:
+            py_tup.c_ob_item[i] = make_ref(space, items_w[i])
             i += 1
     except:
         while i > 0:
             i -= 1
-            decref(space, p[i])
-        lltype.free(p, flavor='raw')
+            ob = py_tup.c_ob_item[i]
+            py_tup.c_ob_item[i] = lltype.nullptr(PyObject.TO)
+            decref(space, ob)
         raise
-    py_tup = rffi.cast(PyTupleObject, py_obj)
-    py_tup.c_ob_size = l
-    py_tup.c_ob_item = p
 
 def tuple_realize(space, py_obj):
     """
@@ -108,7 +107,9 @@
                 "converting a PyTupleObject into a W_TupleObject, "
                 "but found NULLs as items")
         items_w[i] = w_item
-    w_obj = space.newtuple(items_w)
+    w_type = from_ref(space, rffi.cast(PyObject, py_obj.c_ob_type))
+    w_obj = space.allocate_instance(W_TupleObject, w_type)
+    w_obj.__init__(items_w)
     track_reference(space, py_obj, w_obj)
     return w_obj
 
@@ -118,18 +119,16 @@
     """
     py_tup = rffi.cast(PyTupleObject, py_obj)
     p = py_tup.c_ob_item
-    if p:
-        for i in range(py_tup.c_ob_size):
-            decref(space, p[i])
-        lltype.free(p, flavor="raw")
-    from pypy.module.cpyext.object import PyObject_dealloc
-    PyObject_dealloc(space, py_obj)
+    for i in range(py_tup.c_ob_size):
+        decref(space, p[i])
+    from pypy.module.cpyext.object import _dealloc
+    _dealloc(space, py_obj)
 
 #_______________________________________________________________________
 
 @cpython_api([Py_ssize_t], PyObject, result_is_ll=True)
 def PyTuple_New(space, size):
-    return rffi.cast(PyObject, new_empty_tuple(space, size))
+    return new_empty_tuple(space, size)
 
 @cpython_api([PyObject, Py_ssize_t, PyObject], rffi.INT_real, error=-1)
 def PyTuple_SetItem(space, ref, index, py_obj):
@@ -185,25 +184,25 @@
     ref = p_ref[0]
     if not tuple_check_ref(space, ref):
         PyErr_BadInternalCall(space)
-    ref = rffi.cast(PyTupleObject, ref)
-    oldsize = ref.c_ob_size
-    oldp = ref.c_ob_item
-    newp = lltype.malloc(ObjectItems, newsize, zero=True, flavor='raw',
-                         add_memory_pressure=True)
+    oldref = rffi.cast(PyTupleObject, ref)
+    oldsize = oldref.c_ob_size
+    p_ref[0] = new_empty_tuple(space, newsize)
+    newref = rffi.cast(PyTupleObject, p_ref[0])
     try:
         if oldsize < newsize:
             to_cp = oldsize
         else:
             to_cp = newsize
         for i in range(to_cp):
-            newp[i] = oldp[i]
+            ob = oldref.c_ob_item[i]
+            incref(space, ob)
+            newref.c_ob_item[i] = ob
     except:
-        lltype.free(newp, flavor='raw')
+        decref(space, p_ref[0])
+        p_ref[0] = lltype.nullptr(PyObject.TO)
         raise
-    ref.c_ob_item = newp
-    ref.c_ob_size = newsize
-    lltype.free(oldp, flavor='raw')
-    # in this version, p_ref[0] never needs to be updated
+    finally:
+        decref(space, ref)
     return 0
 
 @cpython_api([PyObject, Py_ssize_t, Py_ssize_t], PyObject)
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
@@ -167,7 +167,7 @@
     py_memberdescr.c_d_member = w_obj.member
 
 def memberdescr_realize(space, obj):
-    # XXX NOT TESTED When is this ever called? 
+    # XXX NOT TESTED When is this ever called?
     member = rffi.cast(lltype.Ptr(PyMemberDef), obj)
     w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type))
     w_obj = space.allocate_instance(W_MemberDescr, w_type)
@@ -192,7 +192,7 @@
     py_methoddescr.c_d_method = w_obj.ml
 
 def classmethoddescr_realize(space, obj):
-    # XXX NOT TESTED When is this ever called? 
+    # XXX NOT TESTED When is this ever called?
     method = rffi.cast(lltype.Ptr(PyMethodDef), obj)
     w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type))
     w_obj = space.allocate_instance(W_PyCClassMethodObject, w_type)
@@ -201,7 +201,7 @@
     return w_obj
 
 def methoddescr_realize(space, obj):
-    # XXX NOT TESTED When is this ever called? 
+    # XXX NOT TESTED When is this ever called?
     method = rffi.cast(lltype.Ptr(PyMethodDef), obj)
     w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type))
     w_obj = space.allocate_instance(W_PyCMethodObject, w_type)
@@ -371,6 +371,8 @@
     # (minimally, if tp_basicsize is zero we copy it from the base)
     if not pto.c_tp_basicsize:
         pto.c_tp_basicsize = base_pto.c_tp_basicsize
+    if pto.c_tp_itemsize < base_pto.c_tp_itemsize:
+        pto.c_tp_itemsize = base_pto.c_tp_itemsize
     flags = rffi.cast(lltype.Signed, pto.c_tp_flags)
     base_object_pyo = make_ref(space, space.w_object)
     base_object_pto = rffi.cast(PyTypeObjectPtr, base_object_pyo)
@@ -564,7 +566,7 @@
     if space.is_w(w_type, space.w_str):
         # Special case: str doesn't support get_raw_address(), so we have a
         # custom get*buffer that instead gives the address of the char* in the
-        # PyStringObject*!
+        # PyBytesObject*!
         c_buf.c_bf_getreadbuffer = llhelper(
             str_getreadbuffer.api_func.functype,
             str_getreadbuffer.api_func.get_wrapper(space))
@@ -597,7 +599,7 @@
 
 @cpython_api([PyObject], lltype.Void, header=None)
 def type_dealloc(space, obj):
-    from pypy.module.cpyext.object import PyObject_dealloc
+    from pypy.module.cpyext.object import _dealloc
     obj_pto = rffi.cast(PyTypeObjectPtr, obj)
     base_pyo = rffi.cast(PyObject, obj_pto.c_tp_base)
     Py_DecRef(space, obj_pto.c_tp_bases)
@@ -608,7 +610,7 @@
         heaptype = rffi.cast(PyHeapTypeObject, obj)
         Py_DecRef(space, heaptype.c_ht_name)
         Py_DecRef(space, base_pyo)
-        PyObject_dealloc(space, obj)
+        _dealloc(space, obj)
 
 
 def type_alloc(space, w_metatype, itemsize=0):
@@ -659,6 +661,8 @@
             subtype_dealloc.api_func.get_wrapper(space))
     if space.is_w(w_type, space.w_str):
         pto.c_tp_itemsize = 1
+    elif space.is_w(w_type, space.w_tuple):
+        pto.c_tp_itemsize = rffi.sizeof(PyObject)
     # buffer protocol
     setup_buffer_procs(space, w_type, pto)
 
@@ -778,7 +782,7 @@
 
     if py_type.c_ob_type:
         w_metatype = from_ref(space, rffi.cast(PyObject, py_type.c_ob_type))
-    else: 
+    else:
         # Somehow the tp_base type is created with no ob_type, notably
         # PyString_Type and PyBaseString_Type
         # While this is a hack, cpython does it as well.
@@ -793,10 +797,10 @@
     # inheriting tp_as_* slots
     base = py_type.c_tp_base
     if base:
-        if not py_type.c_tp_as_number: py_type.c_tp_as_number = base.c_tp_as_number 
-        if not py_type.c_tp_as_sequence: py_type.c_tp_as_sequence = base.c_tp_as_sequence 
-        if not py_type.c_tp_as_mapping: py_type.c_tp_as_mapping = base.c_tp_as_mapping 
-        if not py_type.c_tp_as_buffer: py_type.c_tp_as_buffer = base.c_tp_as_buffer 
+        if not py_type.c_tp_as_number: py_type.c_tp_as_number = base.c_tp_as_number
+        if not py_type.c_tp_as_sequence: py_type.c_tp_as_sequence = base.c_tp_as_sequence
+        if not py_type.c_tp_as_mapping: py_type.c_tp_as_mapping = base.c_tp_as_mapping
+        if not py_type.c_tp_as_buffer: py_type.c_tp_as_buffer = base.c_tp_as_buffer
 
     return w_obj
 
diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -90,8 +90,9 @@
     Py_DecRef(space, py_unicode.c_defenc)
     if py_unicode.c_str:
         lltype.free(py_unicode.c_str, flavor="raw")
-    from pypy.module.cpyext.object import PyObject_dealloc
-    PyObject_dealloc(space, py_obj)
+
+    from pypy.module.cpyext.object import _dealloc
+    _dealloc(space, py_obj)
 
 @cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL)
 def Py_UNICODE_ISSPACE(space, ch):
diff --git a/rpython/doc/getting-started.rst b/rpython/doc/getting-started.rst
--- a/rpython/doc/getting-started.rst
+++ b/rpython/doc/getting-started.rst
@@ -142,8 +142,8 @@
 Translating Full Programs
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
-To translate full RPython programs, there is the script ``translate.py`` in
-:source:`rpython/translator/goal`. Examples for this are a slightly changed version of
+To translate full RPython programs, there is the script ``bin/rpython`` in
+:source:`rpython/bin/`. Examples for this are a slightly changed version of
 Pystone::
 
     python bin/rpython translator/goal/targetrpystonedalone
diff --git a/rpython/memory/gctransform/boehm.py b/rpython/memory/gctransform/boehm.py
--- a/rpython/memory/gctransform/boehm.py
+++ b/rpython/memory/gctransform/boehm.py
@@ -1,6 +1,7 @@
 from rpython.memory.gctransform.transform import GCTransformer, mallocHelpers
 from rpython.memory.gctransform.support import (get_rtti,
-    _static_deallocator_body_for_type, LLTransformerOp, ll_call_destructor)
+    _static_deallocator_body_for_type, LLTransformerOp, ll_call_destructor,
+    ll_report_finalizer_error)
 from rpython.rtyper.lltypesystem import lltype, llmemory
 from rpython.flowspace.model import Constant
 from rpython.rtyper.lltypesystem.lloperation import llop
@@ -58,6 +59,9 @@
             self.mixlevelannotator.finish()   # for now
             self.mixlevelannotator.backend_optimize()
 
+        self.finalizer_triggers = []
+        self.finalizer_queue_indexes = {}    # {fq: index}
+
     def gct_fv_gc_malloc(self, hop, flags, TYPE, c_size):
         # XXX same behavior for zero=True: in theory that's wrong
         if TYPE._is_atomic():
@@ -115,6 +119,39 @@
         self.finalizer_funcptrs[TYPE] = fptr
         return fptr
 
+    def get_finalizer_queue_index(self, hop):
+        fq_tag = hop.spaceop.args[0].value
+        assert 'FinalizerQueue TAG' in fq_tag.expr
+        fq = fq_tag.default
+        try:
+            index = self.finalizer_queue_indexes[fq]
+        except KeyError:
+            index = len(self.finalizer_queue_indexes)
+            assert index == len(self.finalizer_triggers)
+            #
+            def ll_finalizer_trigger():
+                try:
+                    fq.finalizer_trigger()
+                except Exception as e:
+                    ll_report_finalizer_error(e)
+            ll_trigger = self.annotate_finalizer(ll_finalizer_trigger, [],
+                                                 lltype.Void)
+            self.finalizer_triggers.append(ll_trigger)
+            self.finalizer_queue_indexes[fq] = index
+        return index
+
+    def gct_gc_fq_register(self, hop):
+        index = self.get_finalizer_queue_index(hop)
+        c_index = rmodel.inputconst(lltype.Signed, index)
+        v_ptr = hop.spaceop.args[1]
+        hop.genop("boehm_fq_register", [c_index, v_ptr])
+
+    def gct_gc_fq_next_dead(self, hop):
+        index = self.get_finalizer_queue_index(hop)
+        c_index = rmodel.inputconst(lltype.Signed, index)
+        hop.genop("boehm_fq_next_dead", [c_index],
+                  resultvar = hop.spaceop.result)
+
     def gct_weakref_create(self, hop):
         v_instance, = hop.spaceop.args
         v_addr = hop.genop("cast_ptr_to_adr", [v_instance],
diff --git a/rpython/rtyper/lltypesystem/ll2ctypes.py b/rpython/rtyper/lltypesystem/ll2ctypes.py
--- a/rpython/rtyper/lltypesystem/ll2ctypes.py
+++ b/rpython/rtyper/lltypesystem/ll2ctypes.py
@@ -166,7 +166,19 @@
         })
 
     if '__int128_t' in rffi.TYPES:
-        _ctypes_cache[rffi.__INT128_T] = ctypes.c_longlong # XXX: Not right at all. But for some reason, It started by while doing JIT compile after a merge with default. Can't extend ctypes, because thats a python standard, right?
+        class c_int128(ctypes.Array):   # based on 2 ulongs
+            _type_ = ctypes.c_uint64
+            _length_ = 2
+            @property
+            def value(self):
+                if sys.byteorder == 'little':
+                    res = self[0] | (self[1] << 64)
+                else:
+                    res = self[1] | (self[0] << 64)
+                if res >= (1 << 127):
+                    res -= 1 << 128
+                return res
+        _ctypes_cache[rffi.__INT128_T] = c_int128
 
     # for unicode strings, do not use ctypes.c_wchar because ctypes
     # automatically converts arrays into unicode strings.
diff --git a/rpython/rtyper/lltypesystem/test/test_rffi.py b/rpython/rtyper/lltypesystem/test/test_rffi.py
--- a/rpython/rtyper/lltypesystem/test/test_rffi.py
+++ b/rpython/rtyper/lltypesystem/test/test_rffi.py
@@ -825,3 +825,13 @@
     assert charp2str(p2) == "helLD"
     free_charp(p1)
     free_charp(p2)
+
+def test_sign_when_casting_uint_to_larger_int():
+    from rpython.rtyper.lltypesystem import rffi
+    from rpython.rlib.rarithmetic import r_uint32, r_uint64
+    #
+    value = 0xAAAABBBB
+    assert cast(lltype.SignedLongLong, r_uint32(value)) == value
+    if hasattr(rffi, '__INT128_T'):
+        value = 0xAAAABBBBCCCCDDDD
+        assert cast(rffi.__INT128_T, r_uint64(value)) == value
diff --git a/rpython/translator/backendopt/finalizer.py b/rpython/translator/backendopt/finalizer.py
--- a/rpython/translator/backendopt/finalizer.py
+++ b/rpython/translator/backendopt/finalizer.py
@@ -36,8 +36,8 @@
                 raise FinalizerError(msg)
         else:
             result = self.analyze_direct_call(graph)
-            if result is self.top_result():
-                log.red('old-style non-light finalizer: %r' % (graph,))
+            #if result is self.top_result():
+            #    log.red('old-style non-light finalizer: %r' % (graph,))
         return result
 
     def analyze_simple_operation(self, op, graphinfo):
diff --git a/rpython/translator/c/gc.py b/rpython/translator/c/gc.py
--- a/rpython/translator/c/gc.py
+++ b/rpython/translator/c/gc.py
@@ -212,6 +212,24 @@
             compile_extra=['-DPYPY_USING_BOEHM_GC'],
             ))
 
+        gct = self.db.gctransformer
+        gct.finalizer_triggers = tuple(gct.finalizer_triggers)  # stop changing
+        sourcelines = ['']
+        for trig in gct.finalizer_triggers:
+            sourcelines.append('RPY_EXTERN void %s(void);' % (
+                self.db.get(trig),))
+        sourcelines.append('')
+        sourcelines.append('void (*boehm_fq_trigger[])(void) = {')
+        for trig in gct.finalizer_triggers:
+            sourcelines.append('\t%s,' % (self.db.get(trig),))
+        sourcelines.append('\tNULL')
+        sourcelines.append('};')
+        sourcelines.append('struct boehm_fq_s *boehm_fq_queues[%d];' % (
+            len(gct.finalizer_triggers),))
+        sourcelines.append('')
+        eci = eci.merge(ExternalCompilationInfo(
+            separate_module_sources=['\n'.join(sourcelines)]))
+
         return eci
 
     def gc_startup_code(self):
diff --git a/rpython/translator/c/src/int.h b/rpython/translator/c/src/int.h
--- a/rpython/translator/c/src/int.h
+++ b/rpython/translator/c/src/int.h
@@ -121,7 +121,7 @@
 #define OP_LLONG_LSHIFT(x,y,r)  CHECK_SHIFT_RANGE(y, PYPY_LONGLONG_BIT); \
                        r = (long long)(((unsigned long long)(x)) << (y))
 #define OP_LLLONG_LSHIFT(x,y,r) CHECK_SHIFT_RANGE(y, 128); \
-                         r = (__int128)(((unsigned __int128)(x)) << (y))
+                         r = (__int128_t)(((__uint128_t)(x)) << (y))
 
 #define OP_UINT_LSHIFT(x,y,r)   CHECK_SHIFT_RANGE(y, PYPY_LONG_BIT);    \
 							r = (x) << (y)
@@ -157,7 +157,7 @@
 #define OP_CAST_UINT_TO_INT(x,r)    r = (Signed)(x)
 #define OP_CAST_INT_TO_UINT(x,r)    r = (Unsigned)(x)
 #define OP_CAST_INT_TO_LONGLONG(x,r) r = (long long)(x)
-#define OP_CAST_INT_TO_LONGLONGLONG(x,r) r = (__int128)(x)
+#define OP_CAST_INT_TO_LONGLONGLONG(x,r) r = (__int128_t)(x)
 #define OP_CAST_CHAR_TO_INT(x,r)    r = (Signed)((unsigned char)(x))
 #define OP_CAST_INT_TO_CHAR(x,r)    r = (char)(x)
 #define OP_CAST_PTR_TO_INT(x,r)     r = (Signed)(x)    /* XXX */
diff --git a/rpython/translator/c/src/mem.c b/rpython/translator/c/src/mem.c
--- a/rpython/translator/c/src/mem.c
+++ b/rpython/translator/c/src/mem.c
@@ -73,9 +73,17 @@
 
 #ifdef PYPY_USING_BOEHM_GC
 
+struct boehm_fq_s {
+    void *obj;
+    struct boehm_fq_s *next;
+};
+RPY_EXTERN void (*boehm_fq_trigger[])(void);
+
 int boehm_gc_finalizer_lock = 0;
 void boehm_gc_finalizer_notifier(void)
 {
+    int i;
+
     boehm_gc_finalizer_lock++;
     while (GC_should_invoke_finalizers()) {
         if (boehm_gc_finalizer_lock > 1) {
@@ -86,6 +94,11 @@
         }
         GC_invoke_finalizers();
     }
+
+    i = 0;
+    while (boehm_fq_trigger[i])
+        boehm_fq_trigger[i++]();
+
     boehm_gc_finalizer_lock--;
 }
 
@@ -100,6 +113,28 @@
     GC_finalize_on_demand = 1;
     GC_set_warn_proc(mem_boehm_ignore);
 }
+
+void boehm_fq_callback(void *obj, void *rawfqueue)
+{
+    struct boehm_fq_s **fqueue = rawfqueue;
+    struct boehm_fq_s *node = GC_malloc(sizeof(void *) * 2);
+    if (!node)
+        return;   /* ouch, too bad */
+    node->obj = obj;
+    node->next = *fqueue;
+    *fqueue = node;
+}
+
+void *boehm_fq_next_dead(struct boehm_fq_s **fqueue)
+{
+    struct boehm_fq_s *node = *fqueue;
+    if (node != NULL) {
+        *fqueue = node->next;
+        return node->obj;
+    }
+    else
+        return NULL;
+}
 #endif /* BOEHM GC */
 
 
diff --git a/rpython/translator/c/src/mem.h b/rpython/translator/c/src/mem.h
--- a/rpython/translator/c/src/mem.h
+++ b/rpython/translator/c/src/mem.h
@@ -104,13 +104,21 @@
 RPY_EXTERN int boehm_gc_finalizer_lock;
 RPY_EXTERN void boehm_gc_startup_code(void);
 RPY_EXTERN void boehm_gc_finalizer_notifier(void);
+struct boehm_fq_s;
+RPY_EXTERN struct boehm_fq_s *boehm_fq_queues[];
+RPY_EXTERN void (*boehm_fq_trigger[])(void);
+RPY_EXTERN void boehm_fq_callback(void *, void *);
+RPY_EXTERN void *boehm_fq_next_dead(struct boehm_fq_s **);
 
 #define OP_GC__DISABLE_FINALIZERS(r)  boehm_gc_finalizer_lock++
 #define OP_GC__ENABLE_FINALIZERS(r)  (boehm_gc_finalizer_lock--,	\
 				      boehm_gc_finalizer_notifier())
 
-#define OP_GC_FQ_REGISTER(tag, obj, r)   /* ignored so far */
-#define OP_GC_FQ_NEXT_DEAD(tag, r)       (r = NULL)
+#define OP_BOEHM_FQ_REGISTER(tagindex, obj, r)                          \
+    GC_REGISTER_FINALIZER(obj, boehm_fq_callback,                       \
+                          boehm_fq_queues + tagindex, NULL, NULL)
+#define OP_BOEHM_FQ_NEXT_DEAD(tagindex, r)                              \
+    r = boehm_fq_next_dead(boehm_fq_queues + tagindex)
 
 #endif /* PYPY_USING_BOEHM_GC */
 
diff --git a/rpython/translator/c/test/test_boehm.py b/rpython/translator/c/test/test_boehm.py
--- a/rpython/translator/c/test/test_boehm.py
+++ b/rpython/translator/c/test/test_boehm.py
@@ -393,20 +393,36 @@
         assert res[3] == compute_hash(d)
         assert res[4] == compute_hash(("Hi", None, (7.5, 2, d)))
 
-    def test_finalizer_queue_is_at_least_ignored(self):
+    def test_finalizer_queue(self):
         class A(object):
-            pass
+            def __init__(self, i):
+                self.i = i
+        class Glob:
+            triggered = 0
+        glob = Glob()
         class FQ(rgc.FinalizerQueue):
             Class = A
+            triggered = 0
             def finalizer_trigger(self):
-                debug.debug_print("hello!")    # not called so far
+                glob.triggered += 1
         fq = FQ()
         #
         def fn():
-            fq.register_finalizer(A())
+            for i in range(1000):
+                fq.register_finalizer(A(i))
             rgc.collect()
             rgc.collect()
-            fq.next_dead()
+            if glob.triggered == 0:
+                print "not triggered!"
+                return 50
+            seen = {}
+            for i in range(1000):
+                a = fq.next_dead()
+                assert a.i not in seen
+                seen[a.i] = True
+            if len(seen) < 500:
+                print "seen only %d!" % len(seen)
+                return 51
             return 42
 
         f = self.getcompiled(fn)


More information about the pypy-commit mailing list