[pypy-svn] r28588 - in pypy/dist/pypy: rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory translator/c translator/c/src

arigo at codespeak.net arigo at codespeak.net
Fri Jun 9 15:55:08 CEST 2006


Author: arigo
Date: Fri Jun  9 15:55:04 2006
New Revision: 28588

Modified:
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/lltypesystem/lloperation.py
   pypy/dist/pypy/rpython/lltypesystem/lltype.py
   pypy/dist/pypy/rpython/lltypesystem/rclass.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_rcpyclass.py
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/rpython/rcpy.py
   pypy/dist/pypy/translator/c/funcgen.py
   pypy/dist/pypy/translator/c/gc.py
   pypy/dist/pypy/translator/c/node.py
   pypy/dist/pypy/translator/c/src/mem.h
Log:
(arre, arigo)
Support deallocation "properly" for PyStruct and rcpy.py.


Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Fri Jun  9 15:55:04 2006
@@ -751,6 +751,9 @@
     def op_gc_call_rtti_destructor(self, rtti, addr):
         raise NotImplementedError("gc_call_rtti_destructor")
 
+    def op_gc_deallocate(self, TYPE, addr):
+        raise NotImplementedError("gc_deallocate")
+
     def op_gc_push_alive_pyobj(self, pyobj):
         raise NotImplementedError("gc_push_alive_pyobj")
 

Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py	Fri Jun  9 15:55:04 2006
@@ -321,6 +321,7 @@
     'gc_fetch_exception':   LLOp(),
     'gc_restore_exception': LLOp(),
     'gc_call_rtti_destructor': LLOp(),
+    'gc_deallocate':        LLOp(),
     'gc_push_alive_pyobj':  LLOp(),
     'gc_pop_alive_pyobj':   LLOp(),
     'gc_protect':           LLOp(),

Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py	Fri Jun  9 15:55:04 2006
@@ -262,8 +262,7 @@
             n = 1
         return _struct(self, n)
 
-class GcStruct(Struct):
-    _gckind = 'gc'
+class RttiStruct(Struct):
     _runtime_type_info = None
 
     def _attach_runtime_type_info_funcptr(self, funcptr, destrptr):
@@ -290,11 +289,14 @@
                                 "implementation, got: %s" % destrptr)
             self._runtime_type_info.destructor_funcptr = destrptr
 
-class PyStruct(Struct):
+class GcStruct(RttiStruct):
+    _gckind = 'gc'
+
+class PyStruct(RttiStruct):
     _gckind = 'cpy'
 
     def __init__(self, name, *fields, **kwds):
-        Struct.__init__(self, name, *fields, **kwds)
+        RttiStruct.__init__(self, name, *fields, **kwds)
         if self._first_struct() == (None, None):
             raise TypeError("a PyStruct must have another PyStruct or "
                             "PyObject as first field")
@@ -457,6 +459,8 @@
     def _inline_is_varsize(self, last):
         raise TypeError, "%r cannot be inlined in structure" % self
 
+FOR_TESTING_ONLY = "for testing only"
+
 class PyObjectType(ContainerType):
     _gckind = 'cpy'
     __name__ = 'PyObject'
@@ -466,10 +470,10 @@
         return False
     def _defl(self, parent=None, parentindex=None, extra_args=()):
         if not extra_args:
-            raise NotImplementedError("PyObjectType._defl()")
+            ob_type = FOR_TESTING_ONLY
         else:
             ob_type = extra_args[0]
-            return _pyobjheader(ob_type, parent, parentindex)
+        return _pyobjheader(ob_type, parent, parentindex)
 
 PyObject = PyObjectType()
 
@@ -1478,7 +1482,8 @@
 
     def __init__(self, ob_type, parent=None, parentindex=None):
         _parentable.__init__(self, PyObject)
-        assert typeOf(ob_type) == Ptr(PyObject)
+        assert (ob_type is FOR_TESTING_ONLY or
+                typeOf(ob_type) == Ptr(PyObject))
         self.ob_type = ob_type
         if parent is not None:
             self._setparentstructure(parent, parentindex)
@@ -1540,22 +1545,22 @@
     return _ptr(PTRTYPE, oddint, solid=True)
 
 def attachRuntimeTypeInfo(GCSTRUCT, funcptr=None, destrptr=None):
-    if not isinstance(GCSTRUCT, GcStruct):
-        raise TypeError, "expected a GcStruct: %s" % GCSTRUCT
+    if not isinstance(GCSTRUCT, RttiStruct):
+        raise TypeError, "expected a RttiStruct: %s" % GCSTRUCT
     GCSTRUCT._attach_runtime_type_info_funcptr(funcptr, destrptr)
     return _ptr(Ptr(RuntimeTypeInfo), GCSTRUCT._runtime_type_info)
 
 def getRuntimeTypeInfo(GCSTRUCT):
-    if not isinstance(GCSTRUCT, GcStruct):
-        raise TypeError, "expected a GcStruct: %s" % GCSTRUCT
+    if not isinstance(GCSTRUCT, RttiStruct):
+        raise TypeError, "expected a RttiStruct: %s" % GCSTRUCT
     if GCSTRUCT._runtime_type_info is None:
         raise ValueError, "no attached runtime type info for %s" % GCSTRUCT
     return _ptr(Ptr(RuntimeTypeInfo), GCSTRUCT._runtime_type_info)
 
 def runtime_type_info(p):
     T = typeOf(p)
-    if not isinstance(T, Ptr) or not isinstance(T.TO, GcStruct):
-        raise TypeError, "runtime_type_info on non-GcStruct pointer: %s" % p
+    if not isinstance(T, Ptr) or not isinstance(T.TO, RttiStruct):
+        raise TypeError, "runtime_type_info on non-RttiStruct pointer: %s" % p
     struct = p._obj
     top_parent = top_container(struct)
     result = getRuntimeTypeInfo(top_parent._TYPE)

Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rclass.py	Fri Jun  9 15:55:04 2006
@@ -85,6 +85,7 @@
             'cpy'  : 'cpy',
             'stack': 'raw',
             }
+RTTIFLAVORS = ('gc', 'cpy')
 
 def cast_vtable_to_typeptr(vtable):
     while typeOf(vtable).TO != OBJECT_VTABLE:
@@ -188,7 +189,7 @@
                 vtable.subclassrange_max = sys.maxint
             rinstance = getinstancerepr(self.rtyper, rsubcls.classdef)
             rinstance.setup()
-            if rinstance.gcflavor == 'gc': # only gc-case
+            if rinstance.gcflavor in RTTIFLAVORS:
                 vtable.rtti = getRuntimeTypeInfo(rinstance.object_type)
             if rsubcls.classdef is None:
                 name = 'object'
@@ -358,11 +359,11 @@
         allinstancefields.update(fields)
         self.fields = fields
         self.allinstancefields = allinstancefields
-        if self.gcflavor == 'gc': # only gc-case
+        if self.gcflavor in RTTIFLAVORS:
             attachRuntimeTypeInfo(self.object_type)
 
     def _setup_repr_final(self):
-        if self.gcflavor == 'gc': # only gc-case
+        if self.gcflavor in RTTIFLAVORS:
             if (self.classdef is not None and
                 self.classdef.classdesc.lookup('__del__') is not None):
                 s_func = self.classdef.classdesc.s_read_attribute('__del__')
@@ -378,6 +379,7 @@
                                        _callable=graph.func)
             else:
                 destrptr = None
+            OBJECT = OBJECT_BY_FLAVOR[LLFLAVOR[self.gcflavor]]
             self.rtyper.attachRuntimeTypeInfoFunc(self.object_type,
                                                   ll_runtime_type_info,
                                                   OBJECT, destrptr)

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rcpyclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_rcpyclass.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_rcpyclass.py	Fri Jun  9 15:55:04 2006
@@ -43,7 +43,6 @@
 
 
 def test_tp_dealloc():
-    import py; py.test.skip("in-progress")
     class mytest(object):
         pass
 

Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Fri Jun  9 15:55:04 2006
@@ -410,7 +410,7 @@
 ADDRESS_VOID_FUNC = lltype.FuncType([llmemory.Address], lltype.Void)
 
 def get_rtti(TYPE):
-    if isinstance(TYPE, lltype.GcStruct):
+    if isinstance(TYPE, lltype.RttiStruct):
         try:
             return lltype.getRuntimeTypeInfo(TYPE)
         except ValueError:
@@ -636,6 +636,16 @@
         self.queryptr2dynamic_deallocator_funcptr[queryptr._obj] = fptr
         return fptr
 
+    def replace_gc_deallocate(self, op, livevars, block):
+        TYPE = op.args[0].value
+        v_addr = op.args[1]
+        dealloc_fptr = self.dynamic_deallocation_funcptr_for_type(TYPE)
+        cdealloc_fptr = rmodel.inputconst(
+            lltype.typeOf(dealloc_fptr), dealloc_fptr)
+        return [SpaceOperation("direct_call", [cdealloc_fptr,
+                                               v_addr],
+                               varoftype(lltype.Void))]
+
 def varoftype(concretetype):
     var = Variable()
     var.concretetype = concretetype

Modified: pypy/dist/pypy/rpython/rcpy.py
==============================================================================
--- pypy/dist/pypy/rpython/rcpy.py	(original)
+++ pypy/dist/pypy/rpython/rcpy.py	Fri Jun  9 15:55:04 2006
@@ -1,6 +1,8 @@
 from pypy.rpython.extregistry import ExtRegistryEntry
 from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.objectmodel import CDefinedIntSymbolic
+from pypy.objspace.flow.model import Constant
 
 
 def cpy_export(cpytype, obj):
@@ -72,7 +74,8 @@
     ('c_tp_name',      lltype.Ptr(lltype.FixedSizeArray(lltype.Char, 1))),
     ('c_tp_basicsize', lltype.Signed),
     ('c_tp_itemsize',  lltype.Signed),
-    ('c_tp_dealloc',   lltype.Signed),
+    ('c_tp_dealloc',   lltype.Ptr(lltype.FuncType([PyObjPtr],
+                                                  lltype.Void))),
     ('c_tp_print',     lltype.Signed),
     ('c_tp_getattr',   lltype.Signed),
     ('c_tp_setattr',   lltype.Signed),   # in
@@ -104,24 +107,31 @@
     ('c_tp_descr_set', lltype.Signed),
     ('c_tp_dictoffset',lltype.Signed),
     ('c_tp_init',      lltype.Signed),
-    ('c_tp_alloc',     lltype.Ptr(lltype.FuncType([lltype.Ptr(PY_TYPE_OBJECT),
-                                                   lltype.Signed],
+    ('c_tp_alloc',     lltype.Signed),
+                       #lltype.Ptr(lltype.FuncType([lltype.Ptr(PY_TYPE_OBJECT),
+                       #                            lltype.Signed],
+                       #                           PyObjPtr))),
+    ('c_tp_new',       lltype.Ptr(lltype.FuncType([lltype.Ptr(PY_TYPE_OBJECT),
+                                                   PyObjPtr,
+                                                   PyObjPtr],
                                                   PyObjPtr))),
-    ('c_tp_new',       lltype.Signed),
-    ('c_tp_free',      lltype.Ptr(lltype.FuncType([llmemory.Address],
-                                                  lltype.Void))),
+    ('c_tp_free',      lltype.Signed),
+                       #lltype.Ptr(lltype.FuncType([llmemory.Address],
+                       #                           lltype.Void))),
 
     hints={'c_name': '_typeobject', 'external': True, 'inline_head': True}))
 # XXX should be PyTypeObject but genc inserts 'struct' :-(
 
-def ll_tp_alloc(tp, itemcount):
-    # XXX pass itemcount too
+def ll_tp_new(tp, args, kwds):
     return lltype.malloc(lltype.PyObject, flavor='cpy', extra_args=(tp,))
 
-def ll_tp_free(addr):
-    # hack: don't cast addr to PyObjPtr, otherwise there is an incref/decref
-    # added around the free!
-    lltype.free(addr, flavor='cpy')
+def ll_tp_dealloc(p):
+    addr = llmemory.cast_ptr_to_adr(p)
+    # Warning: this relies on an optimization in gctransformer, which will
+    # not insert any incref/decref for 'p'.  That would lead to infinite
+    # recursion, as the refcnt of 'p' is already zero!
+    from pypy.rpython.lltypesystem.rclass import CPYOBJECT
+    llop.gc_deallocate(lltype.Void, CPYOBJECT, addr)
 
 def build_pytypeobject(r_inst):
     typetype = lltype.pyobjectptr(type)
@@ -136,10 +146,10 @@
     pytypeobj.c_tp_name = lltype.direct_arrayitems(p)
     pytypeobj.c_tp_basicsize = llmemory.sizeof(r_inst.lowleveltype.TO)
     pytypeobj.c_tp_flags = CDefinedIntSymbolic('Py_TPFLAGS_DEFAULT')
-    pytypeobj.c_tp_alloc = r_inst.rtyper.annotate_helper_fn(
-        ll_tp_alloc,
-        [lltype.Ptr(PY_TYPE_OBJECT), lltype.Signed])
-    pytypeobj.c_tp_free = r_inst.rtyper.annotate_helper_fn(
-        ll_tp_free,
-        [llmemory.Address])
+    pytypeobj.c_tp_new = r_inst.rtyper.annotate_helper_fn(
+        ll_tp_new,
+        [lltype.Ptr(PY_TYPE_OBJECT), PyObjPtr, PyObjPtr])
+    pytypeobj.c_tp_dealloc = r_inst.rtyper.annotate_helper_fn(
+        ll_tp_dealloc,
+        [PyObjPtr])
     return lltype.cast_pointer(PyObjPtr, pytypeobj)

Modified: pypy/dist/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/dist/pypy/translator/c/funcgen.py	(original)
+++ pypy/dist/pypy/translator/c/funcgen.py	Fri Jun  9 15:55:04 2006
@@ -569,7 +569,8 @@
     def OP_FLAVORED_FREE(self, op):
         flavor = op.args[0].value
         if flavor == "raw":
-            return "OP_RAW_FREE(%s)" % (self.expr(op.args[1]),)
+            return "OP_RAW_FREE(%s, %s)" % (self.expr(op.args[1]),
+                                            self.expr(op.result))
         elif flavor == "cpy":
             return "OP_CPY_FREE(%s)" % (self.expr(op.args[1]),)
         else:

Modified: pypy/dist/pypy/translator/c/gc.py
==============================================================================
--- pypy/dist/pypy/translator/c/gc.py	(original)
+++ pypy/dist/pypy/translator/c/gc.py	Fri Jun  9 15:55:04 2006
@@ -2,7 +2,7 @@
 from pypy.translator.c.support import cdecl
 from pypy.translator.c.node import ContainerNode
 from pypy.rpython.lltypesystem.lltype import \
-     typeOf, Ptr, ContainerType, GcArray, GcStruct, \
+     typeOf, Ptr, ContainerType, RttiStruct, \
      RuntimeTypeInfo, getRuntimeTypeInfo, top_container
 from pypy.rpython.memory import gctransform
 from pypy.rpython.lltypesystem import lltype, llmemory
@@ -131,7 +131,7 @@
 
     def __init__(self, db, T, obj):
         assert T == RuntimeTypeInfo
-        assert isinstance(obj.about, GcStruct)
+        assert isinstance(obj.about, RttiStruct)
         self.db = db
         self.T = T
         self.obj = obj
@@ -238,7 +238,7 @@
 
     def __init__(self, db, T, obj):
         assert T == RuntimeTypeInfo
-        assert isinstance(obj.about, GcStruct)
+        assert isinstance(obj.about, RttiStruct)
         self.db = db
         self.T = T
         self.obj = obj

Modified: pypy/dist/pypy/translator/c/node.py
==============================================================================
--- pypy/dist/pypy/translator/c/node.py	(original)
+++ pypy/dist/pypy/translator/c/node.py	Fri Jun  9 15:55:04 2006
@@ -1,7 +1,7 @@
 from __future__ import generators
 from pypy.rpython.lltypesystem.lltype import \
      Struct, Array, FixedSizeArray, FuncType, PyObjectType, typeOf, \
-     GcStruct, GcArray, PyStruct, ContainerType, \
+     GcStruct, GcArray, RttiStruct, PyStruct, ContainerType, \
      parentlink, Ptr, PyObject, Void, OpaqueType, Float, \
      RuntimeTypeInfo, getRuntimeTypeInfo, Char, _subarray, _pyobjheader
 from pypy.rpython.lltypesystem.llmemory import WeakGcAddress
@@ -85,7 +85,7 @@
         self.gcinfo = None   # unless overwritten below
         rtti = None
         STRUCT = self.STRUCT
-        if isinstance(STRUCT, GcStruct):
+        if isinstance(STRUCT, RttiStruct):
             try:
                 rtti = getRuntimeTypeInfo(STRUCT)
             except ValueError:

Modified: pypy/dist/pypy/translator/c/src/mem.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/mem.h	(original)
+++ pypy/dist/pypy/translator/c/src/mem.h	Fri Jun  9 15:55:04 2006
@@ -14,7 +14,7 @@
     r = (void*) alloca(size);                                              \
     if (r == NULL) FAIL_EXCEPTION(PyExc_MemoryError, "out of memory");\
  
-#define OP_RAW_FREE(x)             OP_FREE(x)
+#define OP_RAW_FREE(x,r)           OP_FREE(x)
 #define OP_RAW_MEMCOPY(x,y,size,r) memcpy(y,x,size);
 
 /************************************************************/
@@ -130,4 +130,4 @@
         PyObject_Init((PyObject *)r, (PyTypeObject *)cpytype);  \
     }                                                           \
   }
-#define OP_CPY_FREE(x)   OP_RAW_FREE(x)
+#define OP_CPY_FREE(x)   OP_RAW_FREE(x, /*nothing*/)



More information about the Pypy-commit mailing list