[pypy-svn] r28484 - in pypy/dist/pypy: rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory translator/c translator/tool
arigo at codespeak.net
arigo at codespeak.net
Wed Jun 7 20:31:53 CEST 2006
Author: arigo
Date: Wed Jun 7 20:31:51 2006
New Revision: 28484
Modified:
pypy/dist/pypy/rpython/lltypesystem/llmemory.py
pypy/dist/pypy/rpython/lltypesystem/lltype.py
pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py
pypy/dist/pypy/rpython/memory/gcheader.py
pypy/dist/pypy/rpython/rgc.py
pypy/dist/pypy/translator/c/gc.py
pypy/dist/pypy/translator/c/node.py
pypy/dist/pypy/translator/tool/lltracker.py
Log:
(arre, arigo)
Introduced PyStructs, which are a Struct with PyObject-like memory
management. Streamlined the various _gcstatus() flags to a single
_gckind string that is either 'raw', 'gc' or 'cpy'. The PyStructs
represent custom extensions of PyObject with new fields, for the ext
compiler.
Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py Wed Jun 7 20:31:51 2006
@@ -52,7 +52,7 @@
def raw_malloc(self, rest):
assert not rest
if (isinstance(self.TYPE, lltype.ContainerType)
- and self.TYPE._gcstatus()):
+ and self.TYPE._gckind == 'gc'):
assert self.repeat == 1
p = lltype.malloc(self.TYPE)
return cast_ptr_to_adr(p)
@@ -148,7 +148,7 @@
if self.TYPE._hints.get('isrpystring'):
count -= 1 # because malloc() will give us the extra char for free
p = lltype.malloc(parenttype or self.TYPE, count,
- immortal = not self.TYPE._gcstatus())
+ immortal = self.TYPE._gckind == 'raw')
return cast_ptr_to_adr(p)
Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Wed Jun 7 20:31:51 2006
@@ -136,9 +136,6 @@
class ContainerType(LowLevelType):
_adtmeths = {}
- def _gcstatus(self):
- return isinstance(self, GC_CONTAINER)
-
def _inline_is_varsize(self, last):
raise TypeError, "%r cannot be inlined in structure" % self
@@ -160,6 +157,8 @@
class Struct(ContainerType):
+ _gckind = 'raw'
+
def __init__(self, name, *fields, **kwds):
self._name = self.__name__ = name
flds = {}
@@ -173,12 +172,12 @@
if name in flds:
raise TypeError("%s: repeated field name" % self._name)
flds[name] = typ
- if isinstance(typ, GC_CONTAINER):
- if name == fields[0][0] and isinstance(self, GC_CONTAINER):
- pass # can inline a GC_CONTAINER as 1st field of GcStruct
+ if isinstance(typ, ContainerType) and typ._gckind != 'raw':
+ if name == fields[0][0] and typ._gckind == self._gckind:
+ pass # can inline a XxContainer as 1st field of XxStruct
else:
- raise TypeError("%s: cannot inline GC container %r" % (
- self._name, typ))
+ raise TypeError("%s: cannot inline %s container %r" % (
+ self._name, typ._gckind, typ))
# look if we have an inlined variable-sized array as the last field
if fields:
@@ -197,7 +196,8 @@
if self._names:
first = self._names[0]
FIRSTTYPE = self._flds[first]
- if isinstance(FIRSTTYPE, Struct) and self._gcstatus() == FIRSTTYPE._gcstatus():
+ if (isinstance(FIRSTTYPE, (Struct, PyObjectType)) and
+ self._gckind == FIRSTTYPE._gckind):
return first, FIRSTTYPE
return None, None
@@ -263,6 +263,7 @@
return _struct(self, n)
class GcStruct(Struct):
+ _gckind = 'gc'
_runtime_type_info = None
def _attach_runtime_type_info_funcptr(self, funcptr, destrptr):
@@ -288,9 +289,18 @@
raise TypeError("expected a destructor function "
"implementation, got: %s" % destrptr)
self._runtime_type_info.destructor_funcptr = destrptr
-
+
+class PyStruct(Struct):
+ _gckind = 'cpy'
+
+ def __init__(self, name, *fields, **kwds):
+ Struct.__init__(self, name, *fields, **kwds)
+ if self._first_struct() == (None, None):
+ raise TypeError("a PyStruct must have another PyStruct or "
+ "PyObject as first field")
class Array(ContainerType):
+ _gckind = 'raw'
__name__ = 'array'
_anonym_struct = False
@@ -300,8 +310,9 @@
else:
self.OF = Struct("<arrayitem>", *fields)
self._anonym_struct = True
- if isinstance(self.OF, GC_CONTAINER):
- raise TypeError("cannot have a GC container as array item type")
+ if isinstance(self.OF, ContainerType) and self.OF._gckind != 'raw':
+ raise TypeError("cannot have a %s container as array item type"
+ % (self.OF._gckind,))
self.OF._inline_is_varsize(False)
self._install_extras(**kwds)
@@ -342,6 +353,7 @@
return _array(self, 1)
class GcArray(Array):
+ _gckind = 'gc'
def _inline_is_varsize(self, last):
raise TypeError("cannot inline a GC array inside a structure")
@@ -356,8 +368,9 @@
**kwds)
self.OF = OF
self.length = length
- if isinstance(self.OF, GC_CONTAINER):
- raise TypeError("cannot have a GC container as array item type")
+ if isinstance(self.OF, ContainerType) and self.OF._gckind != 'raw':
+ raise TypeError("cannot have a %s container as array item type"
+ % (self.OF._gckind,))
self.OF._inline_is_varsize(False)
def _str_fields(self):
@@ -377,6 +390,7 @@
class FuncType(ContainerType):
+ _gckind = 'raw'
__name__ = 'func'
def __init__(self, args, result):
for arg in args:
@@ -410,6 +424,7 @@
class OpaqueType(ContainerType):
+ _gckind = 'raw'
def __init__(self, tag):
self.tag = tag
@@ -430,6 +445,7 @@
RuntimeTypeInfo = OpaqueType("RuntimeTypeInfo")
class GcOpaqueType(OpaqueType):
+ _gckind = 'gc'
def __str__(self):
return "%s (gcopaque)" % self.tag
@@ -438,16 +454,23 @@
raise TypeError, "%r cannot be inlined in structure" % self
class PyObjectType(ContainerType):
+ _gckind = 'cpy'
__name__ = 'PyObject'
def __str__(self):
return "PyObject"
+ def _inline_is_varsize(self, last):
+ return False
PyObject = PyObjectType()
class ForwardReference(ContainerType):
+ _gckind = 'raw'
def become(self, realcontainertype):
if not isinstance(realcontainertype, ContainerType):
raise TypeError("ForwardReference can only be to a container, "
"not %r" % (realcontainertype,))
+ if realcontainertype._gckind != self._gckind:
+ raise TypeError("become() gives conflicting gckind, use the "
+ "correct XxForwardReference")
self.__class__ = realcontainertype.__class__
self.__dict__ = realcontainertype.__dict__
@@ -455,15 +478,7 @@
raise TypeError("%r object is not hashable" % self.__class__.__name__)
class GcForwardReference(ForwardReference):
- def become(self, realcontainertype):
- if not isinstance(realcontainertype, GC_CONTAINER):
- raise TypeError("GcForwardReference can only be to GcStruct or "
- "GcArray, not %r" % (realcontainertype,))
- self.__class__ = realcontainertype.__class__
- self.__dict__ = realcontainertype.__dict__
-
-GC_CONTAINER = (GcStruct, GcArray, PyObjectType, GcForwardReference,
- GcOpaqueType)
+ _gckind = 'gc'
class Primitive(LowLevelType):
@@ -531,7 +546,8 @@
self.TO = TO
def _needsgc(self):
- return self.TO._gcstatus()
+ # XXX deprecated interface
+ return self.TO._gckind != 'raw'
def __str__(self):
return '* %s' % (self.TO, )
@@ -540,7 +556,7 @@
return 'Ptr %s' % (self.TO._short_name(), )
def _is_atomic(self):
- return not self.TO._gcstatus()
+ return self.TO._gckind == 'raw'
def _defl(self, parent=None, parentindex=None):
return _ptr(self, None)
@@ -641,7 +657,7 @@
OUTSIDE = getattr(OUTSIDE, first)
def castable(PTRTYPE, CURTYPE):
- if CURTYPE._needsgc() != PTRTYPE._needsgc():
+ if CURTYPE.TO._gckind != PTRTYPE.TO._gckind:
raise TypeError("cast_pointer() cannot change the gc status: %s to %s"
% (CURTYPE, PTRTYPE))
if CURTYPE == PTRTYPE:
@@ -669,7 +685,7 @@
CURTYPE = typeOf(ptr)
if not isinstance(CURTYPE, Ptr) or not isinstance(PTRTYPE, Ptr):
raise TypeError, "can only cast pointers to other pointers"
- if CURTYPE._needsgc() != PTRTYPE._needsgc():
+ if CURTYPE.TO._gckind != PTRTYPE.TO._gckind:
raise TypeError("cast_opaque_ptr() cannot change the gc status: "
"%s to %s" % (CURTYPE, PTRTYPE))
if (isinstance(CURTYPE.TO, OpaqueType)
@@ -813,7 +829,11 @@
def _set_obj0(self, obj):
_ptr._obj0.__set__(self, obj)
+ def _togckind(self):
+ return self._T._gckind
+
def _needsgc(self):
+ # XXX deprecated interface
return self._TYPE._needsgc() # xxx other rules?
def __init__(self, TYPE, pointing_to, solid=False):
@@ -855,7 +875,8 @@
def _setobj(self, pointing_to, solid=False):
if pointing_to is None:
obj0 = None
- elif solid or isinstance(self._T, (GC_CONTAINER, FuncType)):
+ elif (solid or self._T._gckind != 'raw' or
+ isinstance(self._T, FuncType)):
obj0 = pointing_to
else:
self._set_weak(True)
@@ -1091,7 +1112,7 @@
self._parent_index = parentindex
if (isinstance(self._parent_type, Struct)
and parentindex == self._parent_type._names[0]
- and self._TYPE._gcstatus() == typeOf(parent)._gcstatus()):
+ and self._TYPE._gckind == typeOf(parent)._gckind):
# keep strong reference to parent, we share the same allocation
self._keepparent = parent
@@ -1439,7 +1460,7 @@
o = _array(T, n)
else:
raise TypeError, "malloc for Structs and Arrays only"
- if not isinstance(T, GC_CONTAINER) and not immortal and flavor.startswith('gc'):
+ if T._gckind != 'gc' and not immortal and flavor.startswith('gc'):
raise TypeError, "gc flavor malloc of a non-GC non-immortal structure"
solid = immortal or not flavor.startswith('gc') # immortal or non-gc case
return _ptr(Ptr(T), o, solid)
@@ -1448,7 +1469,7 @@
if flavor.startswith('gc'):
raise TypeError, "gc flavor free"
T = typeOf(p)
- if not isinstance(T, Ptr) or p._needsgc():
+ if not isinstance(T, Ptr) or p._togckind() != 'raw':
raise TypeError, "free(): only for pointers to non-gc containers"
def functionptr(TYPE, name, **attrs):
Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py Wed Jun 7 20:31:51 2006
@@ -693,3 +693,12 @@
import gc
gc.collect()
repr(s)
+
+def test_pyobject():
+ p = pyobjectptr({42: 84})
+ assert typeOf(p) == Ptr(PyObject)
+ S1 = PyStruct('S1', ('head', PyObject), ('x', Signed))
+ # cannot really instantiate S1 so far
+ py.test.raises(TypeError, PyStruct, 'S2', ('y', Signed))
+ py.test.raises(TypeError, PyStruct, 'S2', ('x', Struct('X')))
+ py.test.raises(TypeError, PyStruct, 'S2', ('x', GcStruct('X')))
Modified: pypy/dist/pypy/rpython/memory/gcheader.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gcheader.py (original)
+++ pypy/dist/pypy/rpython/memory/gcheader.py Wed Jun 7 20:31:51 2006
@@ -27,7 +27,7 @@
gcobj = gcptr._as_obj()
assert gcobj not in self.obj2header
# sanity checks
- assert isinstance(gcobj._TYPE, lltype.GC_CONTAINER)
+ assert gcobj._TYPE._gckind == 'gc'
assert not isinstance(gcobj._TYPE, lltype.GcOpaqueType)
assert not gcobj._parentstructure()
headerptr = lltype.malloc(self.HDR, immortal=True)
Modified: pypy/dist/pypy/rpython/rgc.py
==============================================================================
--- pypy/dist/pypy/rpython/rgc.py (original)
+++ pypy/dist/pypy/rpython/rgc.py Wed Jun 7 20:31:51 2006
@@ -63,7 +63,7 @@
from pypy.rpython.lltypesystem import lltype, llmemory, rtuple
r_gcobject = hop.args_r[0]
if (not isinstance(r_gcobject.lowleveltype, lltype.Ptr) or
- not isinstance(r_gcobject.lowleveltype.TO, lltype.GC_CONTAINER)):
+ r_gcobject.lowleveltype.TO._gckind != 'gc'):
raise TyperError("gc_clone() can only clone a dynamically "
"allocated object;\ngot %r" % (r_gcobject,))
from pypy.annotation import model as annmodel
Modified: pypy/dist/pypy/translator/c/gc.py
==============================================================================
--- pypy/dist/pypy/translator/c/gc.py (original)
+++ pypy/dist/pypy/translator/c/gc.py Wed Jun 7 20:31:51 2006
@@ -106,7 +106,7 @@
# zero malloc impl
def zero_malloc(self, TYPE, esize, eresult):
- assert TYPE._gcstatus() # we don't really support this
+ assert TYPE._gckind == 'gc' # we don't really support this
return 'OP_ZERO_MALLOC(%s, %s);' % (esize,
eresult)
@@ -186,7 +186,7 @@
def zero_malloc(self, TYPE, esize, eresult):
gcinfo = self.db.gettypedefnode(TYPE).gcinfo
- assert TYPE._gcstatus() # _is_atomic() depends on this!
+ assert TYPE._gckind == 'gc' # _is_atomic() depends on this!
is_atomic = TYPE._is_atomic()
is_varsize = TYPE._is_varsize()
result = 'OP_BOEHM_ZERO_MALLOC(%s, %s, %d, %d);' % (esize,
@@ -320,7 +320,7 @@
gcinfo = defnode.gcinfo
if gcinfo:
if not gcinfo.malloc_exact:
- assert TYPE._gcstatus() # _is_atomic() depends on this!
+ assert TYPE._gckind == 'gc' # _is_atomic() depends on this!
is_atomic = TYPE._is_atomic()
is_varsize = TYPE._is_varsize()
result = 'OP_BOEHM_ZERO_MALLOC(%s, %s, %d, %d);' % (
@@ -393,7 +393,7 @@
return defnode.db.gctransformer.gc_field_values_for(o)
def zero_malloc(self, TYPE, esize, eresult):
- assert TYPE._gcstatus() # we don't really support this
+ assert TYPE._gckind == 'gc' # we don't really support this
return 'OP_ZERO_MALLOC(%s, %s);' % (esize,
eresult)
Modified: pypy/dist/pypy/translator/c/node.py
==============================================================================
--- pypy/dist/pypy/translator/c/node.py (original)
+++ pypy/dist/pypy/translator/c/node.py Wed Jun 7 20:31:51 2006
@@ -1,7 +1,7 @@
from __future__ import generators
from pypy.rpython.lltypesystem.lltype import \
Struct, Array, FixedSizeArray, FuncType, PyObjectType, typeOf, \
- GcStruct, GcArray, GC_CONTAINER, ContainerType, \
+ GcStruct, GcArray, ContainerType, \
parentlink, Ptr, PyObject, Void, OpaqueType, Float, \
RuntimeTypeInfo, getRuntimeTypeInfo, Char, _subarray
from pypy.translator.c.funcgen import FunctionCodeGenerator
@@ -13,10 +13,12 @@
def needs_gcheader(T):
- if not isinstance(T, GC_CONTAINER):
+ if not isinstance(T, ContainerType):
+ return False
+ if T._gckind == 'raw':
return False
if isinstance(T, GcStruct):
- if T._names and isinstance(T._flds[T._names[0]], GC_CONTAINER):
+ if T._first_struct() != (None, None):
return False # gcheader already in the first field
return True
Modified: pypy/dist/pypy/translator/tool/lltracker.py
==============================================================================
--- pypy/dist/pypy/translator/tool/lltracker.py (original)
+++ pypy/dist/pypy/translator/tool/lltracker.py Wed Jun 7 20:31:51 2006
@@ -56,7 +56,7 @@
# XXX clean up
T = lltype.typeOf(o)
if (self.size_gc_header is not None and with_header
- and isinstance(T, lltype.GC_CONTAINER)):
+ and isinstance(T, lltype.ContainerType) and T._gckind == 'gc'):
adr = llmemory.cast_ptr_to_adr(o._as_ptr())
adr -= self.size_gc_header
o = adr.get()._obj
More information about the Pypy-commit
mailing list