[pypy-commit] pypy cpyext-gc-cycle: Removed extra flags in cpython refcount

stevie_92 pypy.commits at gmail.com
Fri Jan 11 05:39:08 EST 2019


Author: Stefan Beyer <home at sbeyer.at>
Branch: cpyext-gc-cycle
Changeset: r95605:878ff32d88a1
Date: 2018-07-05 13:01 +0200
http://bitbucket.org/pypy/pypy/changeset/878ff32d88a1/

Log:	Removed extra flags in cpython refcount Fixed tests in
	test_rawrefcount and test_cpyext Removed references from rawrefcount
	to cpyext Added some comments

diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -1787,10 +1787,10 @@
 
         preexist_error = PyErr_Occurred(space)
         try:
-            print "start cpyext_call"
+            #print "start cpyext_call"
             # Call the function
             result = call_external_function(func, *boxed_args)
-            print "end cpyext_call"
+            #print "end cpyext_call"
         finally:
             assert cpyext_glob_tid_ptr[0] == tid
             cpyext_glob_tid_ptr[0] = tid_before
diff --git a/pypy/module/cpyext/include/boolobject.h b/pypy/module/cpyext/include/boolobject.h
--- a/pypy/module/cpyext/include/boolobject.h
+++ b/pypy/module/cpyext/include/boolobject.h
@@ -13,8 +13,8 @@
 #define Py_True ((PyObject *) &_Py_TrueStruct)
 
 /* Macros for returning Py_True or Py_False, respectively */
-#define Py_RETURN_TRUE do { Py_INCREF(Py_True); return Py_True; } while(0)
-#define Py_RETURN_FALSE do { Py_INCREF(Py_False); return Py_False; } while(0)
+#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
+#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
 
 #ifdef __cplusplus
 }
diff --git a/pypy/module/cpyext/include/object.h b/pypy/module/cpyext/include/object.h
--- a/pypy/module/cpyext/include/object.h
+++ b/pypy/module/cpyext/include/object.h
@@ -2,7 +2,6 @@
 #define Py_OBJECT_H
 
 #include <stdio.h>
-#include <math.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -13,12 +12,7 @@
 #define PY_SSIZE_T_MAX ((Py_ssize_t)(((size_t)-1)>>1))
 #define PY_SSIZE_T_MIN (-PY_SSIZE_T_MAX-1)
 
-#define PY_REFCNT_FROM_PYPY (4L << ((long)(log(PY_SSIZE_T_MAX) / log(2) - 2)))
-#define PY_REFCNT_OVERFLOW (1L << ((long)(log(PY_SSIZE_T_MAX) / log(2) - 4) - 1L))
-#define PY_REFCNT_MASK ((PY_REFCNT_OVERFLOW << 1L) - 1L)
-#define Py_RETURN_NONE return (((((PyObject *)(Py_None))->ob_refcnt & PY_REFCNT_OVERFLOW) == 0) ? \
-                              ((PyObject *)(Py_None))->ob_refcnt++ : Py_IncRef((PyObject *)(Py_None))), Py_None
-
+#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
 
 /*
 CPython has this for backwards compatibility with really old extensions, and now
@@ -40,20 +34,14 @@
 #define Py_XDECREF(ob)  (Py_DecRef((PyObject *)(ob)))
 #else
 /* Fast version */
-#define Py_INCREF(ob)   do {                                                             \
-                            if (!(((PyObject *)(ob))->ob_refcnt & PY_REFCNT_OVERFLOW))   \
-                                ((PyObject *)(ob))->ob_refcnt++;                         \
-                            else                                                         \
-                                Py_IncRef((PyObject *)(ob));                            \
-                        } while (0)
-#define Py_DECREF(ob)   do {                                                                 \
-                            if ((((PyObject *)(ob))->ob_refcnt & PY_REFCNT_OVERFLOW))        \
-                                Py_DecRef((PyObject *)(ob));                                 \
-                            else if (--((PyObject *)(ob))->ob_refcnt & PY_REFCNT_MASK)       \
-                                ;                                                            \
-                            else                                                             \
-                                _Py_Dealloc((PyObject *)(ob));                               \
-                        } while (0)
+#define Py_INCREF(ob)   (((PyObject *)(ob))->ob_refcnt++)
+#define Py_DECREF(op)                                   \
+    do {                                                \
+        if (--((PyObject *)(op))->ob_refcnt != 0)       \
+            ;                                           \
+        else                                            \
+            _Py_Dealloc((PyObject *)(op));              \
+    } while (0)
 
 #define Py_XINCREF(op) do { if ((op) == NULL) ; else Py_INCREF(op); } while (0)
 #define Py_XDECREF(op) do { if ((op) == NULL) ; else Py_DECREF(op); } while (0)
@@ -73,8 +61,7 @@
                 }				\
         } while (0)
 
-#define Py_REFCNT(ob) ((((PyObject *)(ob))->ob_refcnt & PY_REFCNT_OVERFLOW == 0) ?  \
-                      (((PyObject*)(ob))->ob_refcnt & PY_REFCNT_MASK) : _Py_RefCnt_Overflow(ob))
+#define Py_REFCNT(ob)          (((PyObject*)(ob))->ob_refcnt)
 #define Py_TYPE(ob)		(((PyObject*)(ob))->ob_type)
 #define Py_SIZE(ob)		(((PyVarObject*)(ob))->ob_size)
 
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
@@ -11,7 +11,6 @@
 from pypy.module.cpyext.pyerrors import PyErr_NoMemory, PyErr_BadInternalCall
 from pypy.objspace.std.typeobject import W_TypeObject
 from pypy.interpreter.error import OperationError, oefmt
-from rpython.rlib.rawrefcount import REFCNT_MASK
 import pypy.module.__builtin__.operation as operation
 
 
@@ -51,7 +50,7 @@
 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 & REFCNT_MASK == 0
+    assert obj.c_ob_refcnt == 0
     pto = obj.c_ob_type
     obj_voidp = rffi.cast(rffi.VOIDP, obj)
     generic_cpy_call(space, pto.c_tp_free, obj_voidp)
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
@@ -17,11 +17,8 @@
 from rpython.rlib.objectmodel import keepalive_until_here
 from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_base_ptr
 from rpython.rlib import rawrefcount, jit
-from rpython.rlib.debug import ll_assert, fatalerror, debug_print
-from rpython.rlib.rawrefcount import (REFCNT_MASK, REFCNT_FROM_PYPY,
-                                      REFCNT_OVERFLOW)
-from pypy.module.cpyext.api import slot_function
-from pypy.module.cpyext.typeobjectdefs import visitproc
+from rpython.rlib.debug import ll_assert, fatalerror
+
 
 #________________________________________________________
 # type description
@@ -344,7 +341,7 @@
     pyobj = as_pyobj(space, w_obj, w_userdata, immortal=immortal)
     if pyobj:  # != NULL
         assert pyobj.c_ob_refcnt >= rawrefcount.REFCNT_FROM_PYPY
-        rawrefcount.incref(pyobj)
+        pyobj.c_ob_refcnt += 1
         keepalive_until_here(w_obj)
     return pyobj
 
@@ -378,7 +375,7 @@
     pyobj = rffi.cast(PyObject, pyobj)
     w_obj = from_ref(space, pyobj)
     if pyobj:
-        rawrefcount.decref(pyobj)
+        pyobj.c_ob_refcnt -= 1
         assert pyobj.c_ob_refcnt >= rawrefcount.REFCNT_FROM_PYPY
         keepalive_until_here(w_obj)
     return w_obj
@@ -389,7 +386,7 @@
     assert is_pyobj(pyobj)
     pyobj = rffi.cast(PyObject, pyobj)
     assert pyobj.c_ob_refcnt >= 1
-    rawrefcount.incref(pyobj)
+    pyobj.c_ob_refcnt += 1
 
 @specialize.ll()
 def decref(space, pyobj):
@@ -397,9 +394,11 @@
     assert is_pyobj(pyobj)
     pyobj = rffi.cast(PyObject, pyobj)
     if pyobj:
-        rawrefcount.decref(pyobj)
-        rc = pyobj.c_ob_refcnt
-        if rc & REFCNT_MASK == 0:
+        assert pyobj.c_ob_refcnt > 0
+        assert (pyobj.c_ob_pypy_link == 0 or
+                pyobj.c_ob_refcnt > rawrefcount.REFCNT_FROM_PYPY)
+        pyobj.c_ob_refcnt -= 1
+        if pyobj.c_ob_refcnt == 0:
             state = space.fromcache(State)
             generic_cpy_call(space, state.C._Py_Dealloc, pyobj)
         #else:
@@ -407,32 +406,6 @@
         #    if w_obj is not None:
         #        assert pyobj.c_ob_refcnt >= rawrefcount.REFCNT_FROM_PYPY
 
- at cpython_api([PyObject], lltype.Void)
-def Py_IncRef(space, obj):
-    incref(space, obj)
-
- at cpython_api([PyObject], lltype.Void)
-def Py_DecRef(space, obj):
-    decref(space, obj)
-
- at cpython_api([PyObject], lltype.SignedLongLong, error=CANNOT_FAIL)
-def _Py_RefCnt_Overflow(space, obj):
-    return refcnt_overflow(space, obj)
-
- at specialize.ll()
-def refcnt_overflow(space, obj):
-    if is_pyobj(obj):
-        pyobj = rffi.cast(PyObject, obj)
-    else:
-        pyobj = as_pyobj(space, obj, None)
-    if pyobj:
-        if pyobj.c_ob_refcnt & REFCNT_MASK == REFCNT_OVERFLOW:
-            return REFCNT_OVERFLOW
-        else:
-            return (pyobj.c_ob_refcnt & REFCNT_MASK) + \
-                rawrefcount.overflow_get(pyobj)
-    return 0
-
 @init_function
 def write_w_marker_deallocating(space):
     if we_are_translated():
diff --git a/pypy/module/cpyext/src/object.c b/pypy/module/cpyext/src/object.c
--- a/pypy/module/cpyext/src/object.c
+++ b/pypy/module/cpyext/src/object.c
@@ -11,7 +11,6 @@
 extern void _PyPy_Free(void *ptr);
 extern void *_PyPy_Malloc(Py_ssize_t size);
 
-/*
 void
 Py_IncRef(PyObject *o)
 {
@@ -23,7 +22,6 @@
 {
     Py_XDECREF(o);
 }
-*/
 
 /* 
  * The actual value of this variable will be the address of
diff --git a/pypy/module/cpyext/state.py b/pypy/module/cpyext/state.py
--- a/pypy/module/cpyext/state.py
+++ b/pypy/module/cpyext/state.py
@@ -74,8 +74,12 @@
             def tp_traverse(obj_addr, callback, args):
                 # TODO: implement
                 pass
+            # Warning: This list ist different than the list actually used
+            # by the extension modules (see _PyPy_InitPyObjList).
             pyobj_list = lltype.malloc(PyGC_HeadPtr.TO,
                                        flavor='raw', immortal=True, zero=True)
+            pyobj_list.c_gc_next = rffi.cast(rffi.VOIDP, pyobj_list);
+            pyobj_list.c_gc_next = rffi.cast(rffi.VOIDP, pyobj_list);
             rawrefcount.init(dealloc_trigger, tp_traverse, pyobj_list)
         else:
             if space.config.translation.gc == "boehm":
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
@@ -9,12 +9,11 @@
     PyString_ConcatAndDel, PyString_Format, PyString_InternFromString,
     PyString_AsEncodedObject, PyString_AsDecodedObject, _PyString_Eq,
     _PyString_Join)
-from pypy.module.cpyext.api import (
-    PyObjectP, PyObject, Py_ssize_tP, generic_cpy_call)
-from pypy.module.cpyext.pyobject import (
-    Py_DecRef, Py_IncRef, _Py_RefCnt_Overflow, from_ref, make_ref, decref)
+from pypy.module.cpyext.api import PyObjectP, PyObject, Py_ssize_tP, \
+    generic_cpy_call
+from pypy.module.cpyext.pyobject import decref, from_ref, make_ref
 from pypy.module.cpyext.buffer import PyObject_AsCharBuffer
-from rpython.rlib import rawrefcount
+from pypy.module.cpyext.api import PyTypeObjectPtr
 
 
 class AppTestBytesObject(AppTestCpythonExtensionBase):
@@ -512,9 +511,9 @@
         ref = make_ref(space, space.wrap('abc'))
         ptr = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
         ptr[0] = ref
-        prev_refcnt = ref.c_ob_refcnt & rawrefcount.REFCNT_MASK
+        prev_refcnt = ref.c_ob_refcnt
         PyString_Concat(space, ptr, space.wrap('def'))
-        assert ref.c_ob_refcnt & rawrefcount.REFCNT_MASK == prev_refcnt - 1
+        assert ref.c_ob_refcnt == prev_refcnt - 1
         assert space.str_w(from_ref(space, ptr[0])) == 'abcdef'
         with pytest.raises(OperationError):
             PyString_Concat(space, ptr, space.w_None)
@@ -550,9 +549,9 @@
 
         w_text = space.wrap("text")
         ref = make_ref(space, w_text)
-        prev_refcnt = ref.c_ob_refcnt & rawrefcount.REFCNT_MASK
+        prev_refcnt = ref.c_ob_refcnt
         assert PyObject_AsCharBuffer(space, ref, bufp, lenp) == 0
-        assert ref.c_ob_refcnt & rawrefcount.REFCNT_MASK == prev_refcnt
+        assert ref.c_ob_refcnt == prev_refcnt
         assert lenp[0] == 4
         assert rffi.charp2str(bufp[0]) == 'text'
         lltype.free(bufp, flavor='raw')
@@ -611,53 +610,3 @@
         w_seq = space.wrap(['a', 'b'])
         w_joined = _PyString_Join(space, w_sep, w_seq)
         assert space.unwrap(w_joined) == 'a<sep>b'
-
-    def test_refcnt_overflow(self, space):
-        ref1 = make_ref(space, space.wrap('foo'))
-        ref1.c_ob_refcnt = rawrefcount.REFCNT_OVERFLOW - 1
-
-        Py_IncRef(space, ref1)
-        assert ref1.c_ob_refcnt & rawrefcount.REFCNT_MASK \
-            == rawrefcount.REFCNT_OVERFLOW
-        assert _Py_RefCnt_Overflow(space, ref1) \
-            == rawrefcount.REFCNT_OVERFLOW
-
-        Py_IncRef(space, ref1)
-        assert ref1.c_ob_refcnt & rawrefcount.REFCNT_MASK \
-            == rawrefcount.REFCNT_OVERFLOW + 1
-        assert _Py_RefCnt_Overflow(space, ref1) \
-            == rawrefcount.REFCNT_OVERFLOW + 1
-
-        Py_IncRef(space, ref1)
-        assert ref1.c_ob_refcnt & rawrefcount.REFCNT_MASK \
-            == rawrefcount.REFCNT_OVERFLOW + 1
-        assert _Py_RefCnt_Overflow(space, ref1) \
-            == rawrefcount.REFCNT_OVERFLOW + 2
-
-        Py_IncRef(space, ref1)
-        assert ref1.c_ob_refcnt & rawrefcount.REFCNT_MASK \
-            == rawrefcount.REFCNT_OVERFLOW + 1
-        assert _Py_RefCnt_Overflow(space, ref1) \
-            == rawrefcount.REFCNT_OVERFLOW + 3
-
-        Py_DecRef(space, ref1)
-        assert ref1.c_ob_refcnt & rawrefcount.REFCNT_MASK \
-            == rawrefcount.REFCNT_OVERFLOW + 1
-        assert _Py_RefCnt_Overflow(space, ref1) \
-            == rawrefcount.REFCNT_OVERFLOW + 2
-
-        Py_DecRef(space, ref1)
-        assert ref1.c_ob_refcnt & rawrefcount.REFCNT_MASK \
-            == rawrefcount.REFCNT_OVERFLOW + 1
-        assert _Py_RefCnt_Overflow(space, ref1) \
-            == rawrefcount.REFCNT_OVERFLOW + 1
-
-        Py_DecRef(space, ref1)
-        assert ref1.c_ob_refcnt & rawrefcount.REFCNT_MASK \
-            == rawrefcount.REFCNT_OVERFLOW
-        assert _Py_RefCnt_Overflow(space, ref1)  \
-            == rawrefcount.REFCNT_OVERFLOW
-
-        Py_DecRef(space, ref1)
-        assert ref1.c_ob_refcnt & rawrefcount.REFCNT_MASK \
-            == rawrefcount.REFCNT_OVERFLOW - 1
diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -756,7 +756,7 @@
         module = self.import_module(name='foo', init=init, body=body)
 
         # uncaught interplevel exceptions are turned into SystemError
-        expected = "ZeroDivisionError('integer division or modulo by zero',)"
+        expected = "ZeroDivisionError('integer division by zero',)"
         exc = raises(SystemError, module.crash1)
         assert exc.value[0] == expected
 
diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -3107,10 +3107,11 @@
                                       self.singleaddr)
 
     def _rrc_minor_trace(self, pyobject, singleaddr):
-        from rpython.rlib.rawrefcount import REFCNT_MASK
+        from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY
+        from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY_LIGHT
         #
         rc = self._pyobj(pyobject).c_ob_refcnt
-        if rc & REFCNT_MASK == 0:
+        if rc == REFCNT_FROM_PYPY or rc == REFCNT_FROM_PYPY_LIGHT:
             pass     # the corresponding object may die
         else:
             # force the corresponding object to be alive
@@ -3169,12 +3170,11 @@
     def _rrc_free(self, pyobject):
         from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY
         from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY_LIGHT
-        from rpython.rlib.rawrefcount import REFCNT_MASK
         #
         rc = self._pyobj(pyobject).c_ob_refcnt
         if rc >= REFCNT_FROM_PYPY_LIGHT:
             rc -= REFCNT_FROM_PYPY_LIGHT
-            if rc & REFCNT_MASK == 0:
+            if rc == 0:
                 lltype.free(self._pyobj(pyobject), flavor='raw')
             else:
                 # can only occur if LIGHT is used in create_link_pyobj()
@@ -3186,7 +3186,7 @@
                       "refcount underflow from REFCNT_FROM_PYPY_LIGHT?")
             rc -= REFCNT_FROM_PYPY
             self._pyobj(pyobject).c_ob_pypy_link = 0
-            if rc & REFCNT_MASK == 0:
+            if rc == 0:
                 self.rrc_dealloc_pending.append(pyobject)
                 # an object with refcnt == 0 cannot stay around waiting
                 # for its deallocator to be called.  Some code (lxml)
@@ -3212,10 +3212,11 @@
         debug_stop("gc-rrc-trace")
 
     def _rrc_major_trace(self, pyobject, ignore):
-        from rpython.rlib.rawrefcount import REFCNT_MASK
+        from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY
+        from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY_LIGHT
         #
         rc = self._pyobj(pyobject).c_ob_refcnt
-        if rc & REFCNT_MASK == 0:
+        if rc == REFCNT_FROM_PYPY or rc == REFCNT_FROM_PYPY_LIGHT:
             pass     # the corresponding object may die
         else:
             # force the corresponding object to be alive
@@ -3263,11 +3264,11 @@
         self.rrc_more_pyobjects_to_scan = self.AddressStack()
 
     def _rrc_mark_cpyobj(self, pyobj):
-        from rpython.rlib.rawrefcount import REFCNT_VISITED
         # if the pyobj is not marked, remember it and if there is a linked pypy
         # object also remember it
-        if pyobj.c_ob_refcnt & REFCNT_VISITED != REFCNT_VISITED:
-            pyobj.c_ob_refcnt |= REFCNT_VISITED
+        visited = True # TODO: check if visited (via 'cast' to PyGC_Head)
+        if not visited:
+            # TODO: mark visited
             pyobject = llmemory.cast_ptr_to_adr(pyobj)
             self.rrc_more_pyobjects_to_scan.append(pyobject)
             intobj = pyobj.c_ob_pypy_link
@@ -3278,7 +3279,6 @@
                     self.objects_to_trace.append(obj)
 
     def _rrc_major_scan_non_rc_roots(self, pyobject, ignore):
-        from rpython.rlib.rawrefcount import REFCNT_VISITED
         # check in the object header of the linked pypy object, if it is marked
         # or not
         pyobj = self._pyobj(pyobject)
@@ -3286,9 +3286,10 @@
         obj = llmemory.cast_int_to_adr(intobj)
         hdr = self.header(obj)
         if hdr.tid & GCFLAG_VISITED:
-            if pyobj.c_ob_refcnt & REFCNT_VISITED != REFCNT_VISITED:
+            visited = True  # TODO: check if visited
+            if not visited:
                 # process the pyobject now
-                pyobj.c_ob_refcnt |= REFCNT_VISITED
+                # TODO: mark visited
                 self.rrc_pyobjects_to_trace.append(pyobject)
         else:
             # save the pyobject for later, in case its linked object becomes
diff --git a/rpython/memory/gc/test/test_rawrefcount.py b/rpython/memory/gc/test/test_rawrefcount.py
--- a/rpython/memory/gc/test/test_rawrefcount.py
+++ b/rpython/memory/gc/test/test_rawrefcount.py
@@ -2,17 +2,15 @@
 from rpython.rtyper.lltypesystem import lltype, llmemory
 from rpython.memory.gc.incminimark import IncrementalMiniMarkGC
 from rpython.memory.gc.test.test_direct import BaseDirectGCTest
-from rpython.rlib.rawrefcount import (REFCNT_FROM_PYPY, REFCNT_FROM_PYPY_LIGHT,
-                                      REFCNT_MASK)
-from pypy.module.cpyext.api import (PyObject, PyTypeObject, PyTypeObjectPtr,
-                                    PyObjectFields, cpython_struct, PyGC_Head)
-from pypy.module.cpyext.complexobject import PyComplexObject
+from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY
+from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY_LIGHT
 from rpython.rtyper.lltypesystem import rffi
-from pypy.module.cpyext.typeobjectdefs import visitproc, traverseproc
 from rpython.rtyper.annlowlevel import llhelper
-from rpython.rtyper.tool import rffi_platform
+#from pypy.module.cpyext.api import (PyTypeObject)
+#from pypy.module.cpyext.typeobjectdefs import visitproc, traverseproc
 PYOBJ_HDR = IncrementalMiniMarkGC.PYOBJ_HDR
 PYOBJ_HDR_PTR = IncrementalMiniMarkGC.PYOBJ_HDR_PTR
+PYOBJ_GC_HDR_PTR = IncrementalMiniMarkGC.PYOBJ_GC_HDR_PTR
 
 S = lltype.GcForwardReference()
 S.become(lltype.GcStruct('S',
@@ -22,14 +20,14 @@
 
 T = lltype.Ptr(lltype.ForwardReference())
 T.TO.become(lltype.Struct('test',
-                          ('base', PyObject.TO),
+                          ('base', PYOBJ_HDR_PTR.TO),
                           ('next', T),
                           ('prev', T),
                           ('value', lltype.Signed)))
 
-TRAVERSE_FUNCTYPE = rffi.CCallback([PyObject, visitproc, rffi.VOIDP],
-                                   rffi.INT_real)
-t1 = lltype.malloc(PyTypeObject, flavor='raw', immortal=True)
+#TRAVERSE_FUNCTYPE = rffi.CCallback([PYOBJ_HDR_PTR, visitproc, rffi.VOIDP],
+#                                   rffi.INT_real)
+#t1 = lltype.malloc(PyTypeObject, flavor='raw', immortal=True)
 
 
 class TestRawRefCount(BaseDirectGCTest):
@@ -54,11 +52,13 @@
             rc = REFCNT_FROM_PYPY
         self.trigger = []
         self.trigger2 = []
-        self.pyobj_list = lltype.malloc(PyGC_Head.TO, flavor='raw',
+        self.pyobj_list = lltype.malloc(PYOBJ_GC_HDR_PTR.TO, flavor='raw',
                                         immortal=True)
+        self.pyobj_list.c_gc_next = rffi.cast(rffi.VOIDP, self.pyobj_list);
+        self.pyobj_list.c_gc_next = rffi.cast(rffi.VOIDP, self.pyobj_list);
         self.gc.rawrefcount_init(lambda: self.trigger.append(1),
                                  lambda: self.trigger2.append(1),
-                                 self.pyobj_list)
+                                 llmemory.cast_ptr_to_adr(self.pyobj_list))
         #
         if create_immortal:
             p1 = lltype.malloc(S, immortal=True)
@@ -78,10 +78,10 @@
             self._collect(major=False)
             p1 = self.stackroots.pop()
         p1ref = lltype.cast_opaque_ptr(llmemory.GCREF, p1)
-        r1 = lltype.malloc(PyObject.TO, flavor='raw', immortal=create_immortal)
+        r1 = lltype.malloc(PYOBJ_HDR_PTR.TO, flavor='raw', immortal=create_immortal)
         r1.c_ob_refcnt = rc
         r1.c_ob_pypy_link = 0
-        r1.c_ob_type = lltype.nullptr(PyTypeObject)
+        #r1.c_ob_type = lltype.nullptr(PyTypeObject)
         r1addr = llmemory.cast_ptr_to_adr(r1)
         if is_pyobj:
             assert not is_light
@@ -104,40 +104,13 @@
             return p1
         return p1, p1ref, r1, r1addr, check_alive
 
-    def _rawrefcount_cycle_obj(self):
-
-        def test_tp_traverse(obj, visit, args):
-            test = rffi.cast(T, obj)
-            vret = 0
-            if llmemory.cast_ptr_to_adr(test.next).ptr is not None:
-                next = rffi.cast(PyObject, test.next)
-                vret = visit(next, args)
-                if vret != 0:
-                    return vret
-            if llmemory.cast_ptr_to_adr(test.prev).ptr is not None:
-                next = rffi.cast(PyObject, test.prev)
-                vret = visit(next, args)
-                if vret != 0:
-                    return vret
-            return vret
-
-        func_ptr = llhelper(TRAVERSE_FUNCTYPE, test_tp_traverse)
-        rffi_func_ptr = rffi.cast(traverseproc, func_ptr)
-        t1.c_tp_traverse = rffi_func_ptr
-
-        r1 = lltype.malloc(T.TO, flavor='raw', immortal=True)
-        r1.base.c_ob_pypy_link = 0
-        r1.base.c_ob_type = t1
-        r1.base.c_ob_refcnt = 1
-        return r1
-
     def test_rawrefcount_objects_basic(self, old=False):
         p1, p1ref, r1, r1addr, check_alive = (
             self._rawrefcount_pair(42, is_light=True, create_old=old))
         p2 = self.malloc(S)
         p2.x = 84
         p2ref = lltype.cast_opaque_ptr(llmemory.GCREF, p2)
-        r2 = lltype.malloc(PyObject.TO, flavor='raw')
+        r2 = lltype.malloc(PYOBJ_HDR_PTR.TO, flavor='raw')
         r2.c_ob_refcnt = 1
         r2.c_ob_pypy_link = 0
         r2addr = llmemory.cast_ptr_to_adr(r2)
@@ -340,6 +313,33 @@
         self._collect(major=True)
         check_alive(0)
 
+    # def _rawrefcount_cycle_obj(self):
+    #
+    #     def test_tp_traverse(obj, visit, args):
+    #         test = rffi.cast(T, obj)
+    #         vret = 0
+    #         if llmemory.cast_ptr_to_adr(test.next).ptr is not None:
+    #             next = rffi.cast(PYOBJ_HDR_PTR, test.next)
+    #             vret = visit(next, args)
+    #             if vret != 0:
+    #                 return vret
+    #         if llmemory.cast_ptr_to_adr(test.prev).ptr is not None:
+    #             next = rffi.cast(PYOBJ_HDR_PTR, test.prev)
+    #             vret = visit(next, args)
+    #             if vret != 0:
+    #                 return vret
+    #         return vret
+    #
+    #     func_ptr = llhelper(TRAVERSE_FUNCTYPE, test_tp_traverse)
+    #     rffi_func_ptr = rffi.cast(traverseproc, func_ptr)
+    #     t1.c_tp_traverse = rffi_func_ptr
+    #
+    #     r1 = lltype.malloc(T.TO, flavor='raw', immortal=True)
+    #     r1.base.c_ob_pypy_link = 0
+    #     r1.base.c_ob_type = t1
+    #     r1.base.c_ob_refcnt = 1
+    #     return r1
+    #
     # def test_cycle_self_reference_free(self):
     #     self.gc.rawrefcount_init(lambda: self.trigger.append(1))
     #     r1 = self._rawrefcount_cycle_obj()
diff --git a/rpython/rlib/rawrefcount.py b/rpython/rlib/rawrefcount.py
--- a/rpython/rlib/rawrefcount.py
+++ b/rpython/rlib/rawrefcount.py
@@ -4,22 +4,16 @@
 #  This is meant for pypy's cpyext module, but is a generally
 #  useful interface over our GC.  XXX "pypy" should be removed here
 #
-import sys, weakref, py, math
+import sys, weakref, py
 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
 from rpython.rlib.objectmodel import we_are_translated, specialize, not_rpython
 from rpython.rtyper.extregistry import ExtRegistryEntry
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
-from rpython.rlib import rgc, objectmodel
+from rpython.rlib import rgc
 
 
-MAX_BIT = int(math.log(sys.maxint, 2))
-
-# Flags
-REFCNT_FROM_PYPY = 1 << MAX_BIT - 2                             # Reference from a pypy object
-REFCNT_FROM_PYPY_LIGHT = (1 << MAX_BIT - 1) + REFCNT_FROM_PYPY  # Light reference from a pypy object
-REFCNT_VISITED = 1 << MAX_BIT - 3                               # Object visited during marking
-REFCNT_OVERFLOW = 1 << MAX_BIT - 4                              # Overflow bit for reference count
-REFCNT_MASK = (REFCNT_OVERFLOW << 1) - 1                        # Mask for reference count (including overflow bit)
+REFCNT_FROM_PYPY       = sys.maxint // 4 + 1
+REFCNT_FROM_PYPY_LIGHT = REFCNT_FROM_PYPY + (sys.maxint // 2 + 1)
 
 PYOBJ_HDR = lltype.Struct('GCHdr_PyObject',
                           ('c_ob_refcnt', lltype.Signed),
@@ -39,46 +33,6 @@
     _adr2pypy.append(p)
     return res
 
-def incref(pyobj):
-    if pyobj.c_ob_refcnt & REFCNT_OVERFLOW == 0:
-        pyobj.c_ob_refcnt += 1
-    else:
-        if pyobj.c_ob_refcnt & REFCNT_MASK == REFCNT_OVERFLOW:
-            pyobj.c_ob_refcnt += 1
-            overflow_new(pyobj)
-        else:
-            overflow_add(pyobj)
-
-def decref(pyobj):
-    if pyobj.c_ob_refcnt & REFCNT_OVERFLOW == 0:
-        pyobj.c_ob_refcnt -= 1
-    else:
-        if pyobj.c_ob_refcnt & REFCNT_MASK == REFCNT_OVERFLOW:
-            pyobj.c_ob_refcnt -= 1
-        elif overflow_sub(pyobj):
-            pyobj.c_ob_refcnt -= 1
-
-_refcount_overflow = dict()
-
-def overflow_new(obj):
-    _refcount_overflow[objectmodel.current_object_addr_as_int(obj)] = 0
-
-def overflow_add(obj):
-    _refcount_overflow[objectmodel.current_object_addr_as_int(obj)] += 1
-
-def overflow_sub(obj):
-    addr = objectmodel.current_object_addr_as_int(obj)
-    c = _refcount_overflow[addr]
-    if c > 0:
-        _refcount_overflow[addr] = c - 1
-        return False
-    else:
-        _refcount_overflow.pop(addr)
-        return True
-
-def overflow_get(obj):
-    return _refcount_overflow[objectmodel.current_object_addr_as_int(obj)]
-
 
 @not_rpython
 def init(dealloc_trigger_callback=None, tp_traverse=None, pyobj_list=None):
@@ -189,8 +143,7 @@
     wr_p_list = []
     new_p_list = []
     for ob in reversed(_p_list):
-        if ob.c_ob_refcnt & REFCNT_MASK > 0 \
-           or ob.c_ob_refcnt & REFCNT_FROM_PYPY == 0:
+        if ob.c_ob_refcnt not in (REFCNT_FROM_PYPY, REFCNT_FROM_PYPY_LIGHT):
             new_p_list.append(ob)
         else:
             p = detach(ob, wr_p_list)
@@ -223,8 +176,7 @@
             if ob.c_ob_refcnt >= REFCNT_FROM_PYPY_LIGHT:
                 ob.c_ob_refcnt -= REFCNT_FROM_PYPY_LIGHT
                 ob.c_ob_pypy_link = 0
-                if ob.c_ob_refcnt & REFCNT_MASK == 0 \
-                   and ob.c_ob_refcnt < REFCNT_FROM_PYPY:
+                if ob.c_ob_refcnt == 0:
                     lltype.free(ob, flavor='raw',
                                 track_allocation=track_allocation)
             else:
@@ -232,9 +184,8 @@
                 assert ob.c_ob_refcnt < int(REFCNT_FROM_PYPY_LIGHT * 0.99)
                 ob.c_ob_refcnt -= REFCNT_FROM_PYPY
                 ob.c_ob_pypy_link = 0
-                if ob.c_ob_refcnt & REFCNT_MASK == 0 \
-                   and ob.c_ob_refcnt < REFCNT_FROM_PYPY:
-                    ob.c_ob_refcnt += 1
+                if ob.c_ob_refcnt == 0:
+                    ob.c_ob_refcnt = 1
                     _d_list.append(ob)
             return None
 
diff --git a/rpython/rtyper/rclass.py b/rpython/rtyper/rclass.py
--- a/rpython/rtyper/rclass.py
+++ b/rpython/rtyper/rclass.py
@@ -915,6 +915,10 @@
                             lst.append(str(g))
                             g = seen.get(g)
                         lst.append('')
+                        # TODO: remove code (see below) to make this check pass
+                        # pypy/module/cpyext/api.py:
+                        #   print "start cpyext_call"
+                        #   print "end cpyext_call"
                         raise TyperError("the RPython-level __del__() method "
                                          "in %r calls:%s" %
                                          (graph, '\n\t'.join(lst[::-1])))


More information about the pypy-commit mailing list