[pypy-commit] pypy cpyext-gc-support-2: Hopefully fix the bootstrap cycles in this way

arigo pypy.commits at gmail.com
Tue Jan 26 19:19:56 EST 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: cpyext-gc-support-2
Changeset: r81965:ae316294940c
Date: 2016-01-27 01:04 +0100
http://bitbucket.org/pypy/pypy/changeset/ae316294940c/

Log:	Hopefully fix the bootstrap cycles in this way

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
@@ -310,13 +310,24 @@
                    realize=type_realize,
                    dealloc=type_dealloc)
 
-    # we create the type "type" manually here, because of the cycle
-    # through its 'c_ob_type' field
+    # There is the obvious cycle of 'type(type) == type', but there are
+    # also several other ones, like 'tuple.tp_bases' being itself a
+    # tuple instance.  We solve the first one by creating the type
+    # "type" manually here.  For the other cycles, we fix them by delaying
+    # creation of the types here, and hoping nothing breaks by seeing
+    # uninitialized-yet types (only for a few basic types like 'type',
+    # 'tuple', 'object', 'str').
+    space._cpyext_delay_type_creation = []
+
     py_type   = _type_alloc(space, lltype.nullptr(PyTypeObject))
     py_type.c_ob_type = rffi.cast(PyTypeObjectPtr, py_type)
     track_reference(space, py_type, space.w_type)
     type_attach(space, py_type, space.w_type)
 
+    while space._cpyext_delay_type_creation:
+        _type_really_attach(space, *space._cpyext_delay_type_creation.pop())
+    del space._cpyext_delay_type_creation
+
 
 @cpython_api([PyObject], lltype.Void, external=False)
 def subtype_dealloc(space, obj):
@@ -447,6 +458,13 @@
     """
     Fills a newly allocated PyTypeObject from an existing type.
     """
+    if hasattr(space, '_cpyext_delay_type_creation'):
+        space._cpyext_delay_type_creation.append((py_obj, w_type))
+    else:
+        _type_really_attach(space, py_obj, w_type)
+    return rffi.cast(PyTypeObjectPtr, py_obj)
+
+def _type_really_attach(space, py_obj, w_type):
     from pypy.module.cpyext.object import PyObject_Del
 
     assert isinstance(w_type, W_TypeObject)
@@ -499,7 +517,6 @@
         pto.c_tp_name = rffi.str2charp(w_type.name)
 
     pto.c_tp_flags |= Py_TPFLAGS_READY
-    return pto
 
 def py_type_ready(space, pto):
     if pto.c_tp_flags & Py_TPFLAGS_READY:
@@ -513,6 +530,7 @@
 
 def type_realize(space, py_obj):
     pto = rffi.cast(PyTypeObjectPtr, py_obj)
+    assert pto.c_tp_flags & Py_TPFLAGS_READY == 0
     assert pto.c_tp_flags & Py_TPFLAGS_READYING == 0
     pto.c_tp_flags |= Py_TPFLAGS_READYING
     try:
@@ -590,7 +608,8 @@
     base = pto.c_tp_base
     base_pyo = rffi.cast(PyObject, pto.c_tp_base)
     if base and not base.c_tp_flags & Py_TPFLAGS_READY:
-        type_realize(space, rffi.cast(PyObject, base_pyo))
+        if not hasattr(space, '_cpyext_delay_type_creation'):
+            type_realize(space, rffi.cast(PyObject, base_pyo))
     if base and not pto.c_ob_type: # will be filled later
         pto.c_ob_type = base.c_ob_type
     if not pto.c_tp_bases:
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -164,6 +164,10 @@
             else:
                 w_self.terminator = NoDictTerminator(space, w_self)
 
+    def __repr__(self):
+        "NOT_RPYTHON"
+        return '<W_TypeObject %r at 0x%x>' % (self.name, id(self))
+
     def mutated(w_self, key):
         """
         The type is being mutated. key is either the string containing the


More information about the pypy-commit mailing list