[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