[pypy-svn] r32250 - in pypy/branch/kill-keepalives/pypy: annotation rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory rpython/rctypes rpython/test translator/c translator/c/src
mwh at codespeak.net
mwh at codespeak.net
Wed Sep 13 11:50:55 CEST 2006
Author: mwh
Date: Wed Sep 13 11:50:52 2006
New Revision: 32250
Modified:
pypy/branch/kill-keepalives/pypy/annotation/bookkeeper.py
pypy/branch/kill-keepalives/pypy/annotation/model.py
pypy/branch/kill-keepalives/pypy/annotation/unaryop.py
pypy/branch/kill-keepalives/pypy/rpython/llinterp.py
pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/llmemory.py
pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lloperation.py
pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lltype.py
pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/opimpl.py
pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/rdict.py
pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/rstr.py
pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/test/test_lltype.py
pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/test/test_picklelltype.py
pypy/branch/kill-keepalives/pypy/rpython/memory/convertlltype.py
pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py
pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py
pypy/branch/kill-keepalives/pypy/rpython/rptr.py
pypy/branch/kill-keepalives/pypy/rpython/test/test_rdict.py
pypy/branch/kill-keepalives/pypy/rpython/test/test_rptr.py
pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py
pypy/branch/kill-keepalives/pypy/translator/c/src/support.h
Log:
svn merge -r32048:32248 http://codespeak.net/svn/pypy/branch/more-gckinds .
Modified: pypy/branch/kill-keepalives/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/branch/kill-keepalives/pypy/annotation/bookkeeper.py (original)
+++ pypy/branch/kill-keepalives/pypy/annotation/bookkeeper.py Wed Sep 13 11:50:52 2006
@@ -11,7 +11,7 @@
SomeInteger, SomeExternalObject, SomeOOInstance, TLS, SomeAddress, \
SomeUnicodeCodePoint, SomeOOStaticMeth, s_None, s_ImpossibleValue, \
SomeLLADTMeth, SomeBool, SomeTuple, SomeOOClass, SomeImpossibleValue, \
- SomeList, SomeObject, SomeWeakGcAddress
+ SomeList, SomeObject, SomeWeakGcAddress, lltype_to_annotation
from pypy.annotation.classdef import ClassDef, InstanceSource
from pypy.annotation.listdef import ListDef, MOST_GENERAL_LISTDEF
from pypy.annotation.dictdef import DictDef, MOST_GENERAL_DICTDEF
@@ -237,7 +237,7 @@
if isinstance(s_callable, SomeLLADTMeth):
adtmeth = s_callable
s_callable = self.immutablevalue(adtmeth.func)
- args_s = [SomePtr(adtmeth.ll_ptrtype)] + args_s
+ args_s = [lltype_to_annotation(adtmeth.ll_ptrtype)] + args_s
if isinstance(s_callable, SomePBC):
s_result = binding(call_op.result, s_ImpossibleValue)
self.consider_call_site_for_pbc(s_callable,
Modified: pypy/branch/kill-keepalives/pypy/annotation/model.py
==============================================================================
--- pypy/branch/kill-keepalives/pypy/annotation/model.py (original)
+++ pypy/branch/kill-keepalives/pypy/annotation/model.py Wed Sep 13 11:50:52 2006
@@ -515,6 +515,11 @@
def can_be_none(self):
return False
+class SomeInteriorPtr(SomePtr):
+ def __init__(self, ll_ptrtype):
+ assert isinstance(ll_ptrtype, lltype.InteriorPtr)
+ self.ll_ptrtype = ll_ptrtype
+
class SomeLLADTMeth(SomeObject):
immutable = True
def __init__(self, ll_ptrtype, func):
@@ -563,6 +568,13 @@
return s_val.ootype
if isinstance(s_val, SomeOOStaticMeth):
return s_val.method
+ if isinstance(s_val, SomeInteriorPtr):
+ p = s_val.ll_ptrtype
+ if 0 in p.offsets:
+ assert list(p.offsets).count(0) == 1
+ return lltype.Ptr(lltype.Ptr(p.PARENTTYPE)._interior_ptr_type_with_index(p.TO))
+ else:
+ return lltype.Ptr(p.PARENTTYPE)
if isinstance(s_val, SomePtr):
return s_val.ll_ptrtype
for witness, T in annotation_to_ll_map:
@@ -596,6 +608,8 @@
return SomeOOClass(ootype.ROOT)
elif isinstance(T, ExternalType):
return SomeExternalBuiltin(T)
+ elif isinstance(T, lltype.InteriorPtr):
+ return SomeInteriorPtr(T)
else:
return SomePtr(T)
else:
@@ -609,13 +623,19 @@
return getbookkeeper().immutablevalue(None)
if isinstance(v, MethodType):
ll_ptrtype = lltype.typeOf(v.im_self)
- assert isinstance(ll_ptrtype, lltype.Ptr)
+ assert isinstance(ll_ptrtype, (lltype.Ptr, lltype.InteriorPtr))
return SomeLLADTMeth(ll_ptrtype, v.im_func)
if isinstance(v, FunctionType):
# this case should only be for staticmethod instances used in
# adtmeths: the getattr() result is then a plain FunctionType object.
from pypy.annotation.bookkeeper import getbookkeeper
return getbookkeeper().immutablevalue(v)
+ if isinstance(v, lltype._interior_ptr):
+ ob = v._parent
+ if ob is None:
+ raise RuntimeError
+ T = lltype.InteriorPtr(lltype.typeOf(ob), v._T, v._offsets)
+ return SomeInteriorPtr(T)
return lltype_to_annotation(lltype.typeOf(v))
# ____________________________________________________________
Modified: pypy/branch/kill-keepalives/pypy/annotation/unaryop.py
==============================================================================
--- pypy/branch/kill-keepalives/pypy/annotation/unaryop.py (original)
+++ pypy/branch/kill-keepalives/pypy/annotation/unaryop.py Wed Sep 13 11:50:52 2006
@@ -671,7 +671,7 @@
def call(adtmeth, args):
bookkeeper = getbookkeeper()
s_func = bookkeeper.immutablevalue(adtmeth.func)
- return s_func.call(args.prepend(SomePtr(adtmeth.ll_ptrtype)))
+ return s_func.call(args.prepend(lltype_to_annotation(adtmeth.ll_ptrtype)))
from pypy.rpython.ootypesystem import ootype
class __extend__(SomeOOInstance):
Modified: pypy/branch/kill-keepalives/pypy/rpython/llinterp.py
==============================================================================
--- pypy/branch/kill-keepalives/pypy/rpython/llinterp.py (original)
+++ pypy/branch/kill-keepalives/pypy/rpython/llinterp.py Wed Sep 13 11:50:52 2006
@@ -486,6 +486,18 @@
op_bare_setfield = op_setfield
+ def op_setinteriorfield(self, obj, *fieldnamesval):
+ prefields, finalfield, fieldvalue = fieldnamesval[:-2], fieldnamesval[-2], fieldnamesval[-1]
+ for o in prefields:
+ if isinstance(o, str):
+ obj = getattr(obj, o)
+ else:
+ obj = obj[o]
+ if isinstance(finalfield, str):
+ setattr(obj, finalfield, fieldvalue)
+ else:
+ obj[finalfield] = fieldvalue
+
def op_getarrayitem(self, array, index):
return array[index]
Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/llmemory.py (original)
+++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/llmemory.py Wed Sep 13 11:50:52 2006
@@ -47,7 +47,7 @@
def ref(self, firstitemref):
assert isinstance(firstitemref, _arrayitemref)
array = firstitemref.array
- assert lltype.typeOf(array).TO.OF == self.TYPE
+ assert lltype.rawTypeOf(array).TO.OF == self.TYPE
index = firstitemref.index + self.repeat
return _arrayitemref(array, index)
@@ -76,7 +76,7 @@
def ref(self, containerref):
struct = containerref.get()
- if lltype.typeOf(struct).TO != self.TYPE:
+ if lltype.rawTypeOf(struct).TO != self.TYPE:
struct = lltype.cast_pointer(lltype.Ptr(self.TYPE), struct)
return _structfieldref(struct, self.fldname)
@@ -136,7 +136,7 @@
def ref(self, arrayref):
array = arrayref.get()
- assert lltype.typeOf(array).TO == self.TYPE
+ assert lltype.rawTypeOf(array).TO == self.TYPE
return _arrayitemref(array, index=0)
def raw_malloc(self, rest, parenttype=None):
@@ -164,7 +164,7 @@
def ref(self, arrayref):
array = arrayref.get()
- assert lltype.typeOf(array).TO == self.TYPE
+ assert lltype.rawTypeOf(array).TO == self.TYPE
return _arraylenref(array)
@@ -229,7 +229,7 @@
def __ne__(self, other):
return not (self == other)
def type(self):
- return lltype.typeOf(self.array).TO.OF
+ return lltype.rawTypeOf(self.array).TO.OF
class _arraylenref(object):
def __init__(self, array):
@@ -264,7 +264,7 @@
def __ne__(self, other):
return not (self == other)
def type(self):
- return getattr(lltype.typeOf(self.struct).TO, self.fieldname)
+ return getattr(lltype.rawTypeOf(self.struct).TO, self.fieldname)
class _obref(object):
def __init__(self, ob):
Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lloperation.py (original)
+++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lloperation.py Wed Sep 13 11:50:52 2006
@@ -303,8 +303,11 @@
'getarrayitem': LLOp(sideeffects=False, canrun=True),
'getarraysize': LLOp(canfold=True),
'getsubstruct': LLOp(canfold=True),
+ 'getinteriorfield': LLOp(canfold=True), # XXX not sure about the foldability...
+ 'getinteriorarraysize': LLOp(canfold=True),
'getarraysubstruct': LLOp(canfold=True),
'setfield': LLOp(),
+ 'setinteriorfield': LLOp(),
'bare_setfield': LLOp(),
'setarrayitem': LLOp(),
'cast_pointer': LLOp(canfold=True),
Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lltype.py (original)
+++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lltype.py Wed Sep 13 11:50:52 2006
@@ -616,6 +616,34 @@
o = self.TO._container_example()
return _ptr(self, o, solid=True)
+ def _interior_ptr_type_with_index(self, TO):
+ assert self.TO._gckind == 'gc'
+ if isinstance(TO, Struct):
+ R = GcStruct("Interior", ('ptr', self), ('index', Signed),
+ hints={'interior_ptr_type':True},
+ adtmeths=TO._adtmeths)
+ else:
+ R = GcStruct("Interior", ('ptr', self), ('index', Signed),
+ hints={'interior_ptr_type':True})
+ return R
+
+class InteriorPtr(LowLevelType):
+ def __init__(self, PARENTTYPE, TO, offsets):
+ self.PARENTTYPE = PARENTTYPE
+ self.TO = TO
+ self.offsets = tuple(offsets)
+ def __str__(self):
+ return '%s (%s).%s'%(self.__class__.__name__,
+ self.PARENTTYPE._short_name(),
+ '.'.join(map(str, self.offsets)))
+ def _example(self):
+ ob = Ptr(self.PARENTTYPE)._example()
+ for o in self.offsets:
+ if isinstance(o, str):
+ ob = getattr(ob, o)
+ else:
+ ob = ob[0]
+ return ob
# ____________________________________________________________
@@ -647,6 +675,12 @@
return val.lltype()
raise TypeError("typeOf(%r object)" % (tp.__name__,))
+def rawTypeOf(val):
+ if isinstance(val, _interior_ptr):
+ return Ptr(val._T)
+ else:
+ return typeOf(val)
+
_to_primitive = {
Char: chr,
UniChar: unichr,
@@ -821,13 +855,6 @@
parent, base = parentlink(ptr._obj)
return _subarray._makeptr(parent, base + n, ptr._solid)
-def _expose(val, solid=False):
- """XXX A nice docstring here"""
- T = typeOf(val)
- if isinstance(T, ContainerType):
- val = _ptr(Ptr(T), val, solid=solid)
- return val
-
def parentlink(container):
parent = container._parentstructure()
if parent is not None:
@@ -874,26 +901,14 @@
class UninitializedMemoryAccess(Exception):
pass
-class _ptr(object):
- __slots__ = ('_TYPE', '_T',
- '_weak', '_solid',
- '_obj0', '__weakref__')
+class _abstract_ptr(object):
+ __slots__ = ('_T',)
- def _set_TYPE(self, TYPE):
- _ptr._TYPE.__set__(self, TYPE)
+ # assumes one can access _TYPE, _expose and _obj
def _set_T(self, T):
_ptr._T.__set__(self, T)
- def _set_weak(self, weak):
- _ptr._weak.__set__(self, weak)
-
- def _set_solid(self, solid):
- _ptr._solid.__set__(self, solid)
-
- def _set_obj0(self, obj):
- _ptr._obj0.__set__(self, obj)
-
def _togckind(self):
return self._T._gckind
@@ -901,19 +916,8 @@
# XXX deprecated interface
return self._TYPE._needsgc() # xxx other rules?
- def __init__(self, TYPE, pointing_to, solid=False):
- self._set_TYPE(TYPE)
- self._set_T(TYPE.TO)
- self._set_weak(False)
- self._setobj(pointing_to, solid)
-
- def _become(self, other):
- assert self._TYPE == other._TYPE
- assert not self._weak
- self._setobj(other._obj, other._solid)
-
def __eq__(self, other):
- if not isinstance(other, _ptr):
+ if type(self) is not type(other):
raise TypeError("comparing pointer with %r object" % (
type(other).__name__,))
if self._TYPE != other._TYPE:
@@ -929,46 +933,11 @@
def __hash__(self):
raise TypeError("pointer objects are not hashable")
- def __nonzero__(self):
- try:
- return self._obj is not None
- except DelayedPointer:
- return True # assume it's not a delayed null
-
- # _setobj, _getobj and _obj0 are really _internal_ implementations details of _ptr,
- # use _obj if necessary instead !
- def _setobj(self, pointing_to, solid=False):
- if pointing_to is None:
- obj0 = None
- elif (solid or self._T._gckind != 'raw' or
- isinstance(self._T, FuncType)):
- obj0 = pointing_to
- else:
- self._set_weak(True)
- obj0 = pickleable_weakref(pointing_to)
- self._set_solid(solid)
- self._set_obj0(obj0)
-
- def _getobj(self):
- obj = self._obj0
- if obj is not None:
- if self._weak:
- obj = obj()
- if obj is None:
- raise RuntimeError("accessing already garbage collected %r"
- % (self._T,))
- if isinstance(obj, _container):
- obj._check()
- elif isinstance(obj, str) and obj.startswith("delayed!"):
- raise DelayedPointer
- return obj
- _obj = property(_getobj)
-
def __getattr__(self, field_name): # ! can only return basic or ptr !
if isinstance(self._T, Struct):
if field_name in self._T._flds:
o = self._obj._getattr(field_name)
- return _expose(o, self._solid)
+ return self._expose(field_name, o)
if isinstance(self._T, ContainerType):
try:
adtmeth = self._T._adtmeths[field_name]
@@ -984,20 +953,6 @@
raise AttributeError("%r instance has no field %r" % (self._T,
field_name))
- #def _setfirst(self, p):
- # if isinstance(self._T, Struct) and self._T._names:
- # if not isinstance(p, _ptr) or not isinstance(p._obj, _struct):
- # raise InvalidCast(typeOf(p), typeOf(self))
- # field_name = self._T._names[0]
- # T1 = self._T._flds[field_name]
- # T2 = typeOf(p._obj)
- # if T1 != T2:
- # raise InvalidCast(typeOf(p), typeOf(self))
- # setattr(self._obj, field_name, p._obj)
- # p._obj._setparentstructure(self._obj, 0)
- # return
- # raise TypeError("%r instance has no first field" % (self._T,))
-
def __setattr__(self, field_name, val):
if isinstance(self._T, Struct):
if field_name in self._T._flds:
@@ -1021,7 +976,7 @@
raise TypeError("array slicing not supported")
raise IndexError("array index out of bounds")
o = self._obj.getitem(i)
- return _expose(o, self._solid)
+ return self._expose(i, o)
raise TypeError("%r instance is not an array" % (self._T,))
def __setitem__(self, i, val):
@@ -1084,6 +1039,69 @@
__getstate__ = getstate_with_slots
__setstate__ = setstate_with_slots
+class _ptr(_abstract_ptr):
+ __slots__ = ('_TYPE',
+ '_weak', '_solid',
+ '_obj0', '__weakref__')
+
+ def _set_TYPE(self, TYPE):
+ _ptr._TYPE.__set__(self, TYPE)
+
+ def _set_weak(self, weak):
+ _ptr._weak.__set__(self, weak)
+
+ def _set_solid(self, solid):
+ _ptr._solid.__set__(self, solid)
+
+ def _set_obj0(self, obj):
+ _ptr._obj0.__set__(self, obj)
+
+ def __init__(self, TYPE, pointing_to, solid=False):
+ self._set_TYPE(TYPE)
+ self._set_T(TYPE.TO)
+ self._set_weak(False)
+ self._setobj(pointing_to, solid)
+
+ def _become(self, other):
+ assert self._TYPE == other._TYPE
+ assert not self._weak
+ self._setobj(other._obj, other._solid)
+
+ def __nonzero__(self):
+ try:
+ return self._obj is not None
+ except DelayedPointer:
+ return True # assume it's not a delayed null
+
+ # _setobj, _getobj and _obj0 are really _internal_ implementations details of _ptr,
+ # use _obj if necessary instead !
+ def _setobj(self, pointing_to, solid=False):
+ if pointing_to is None:
+ obj0 = None
+ elif (solid or self._T._gckind != 'raw' or
+ isinstance(self._T, FuncType)):
+ obj0 = pointing_to
+ else:
+ self._set_weak(True)
+ obj0 = pickleable_weakref(pointing_to)
+ self._set_solid(solid)
+ self._set_obj0(obj0)
+
+ def _getobj(self):
+ obj = self._obj0
+ if obj is not None:
+ if self._weak:
+ obj = obj()
+ if obj is None:
+ raise RuntimeError("accessing already garbage collected %r"
+ % (self._T,))
+ if isinstance(obj, _container):
+ obj._check()
+ elif isinstance(obj, str) and obj.startswith("delayed!"):
+ raise DelayedPointer
+ return obj
+ _obj = property(_getobj)
+
def _cast_to(self, PTRTYPE):
CURTYPE = self._TYPE
down_or_up = castable(PTRTYPE, CURTYPE)
@@ -1145,8 +1163,67 @@
def _as_obj(self):
return self._obj
+ def _expose(self, offset, val):
+ """XXX A nice docstring here"""
+ T = typeOf(val)
+ if isinstance(T, ContainerType):
+ if self._T._gckind == 'gc' and T._gckind == 'raw' and not isinstance(T, OpaqueType):
+ val = _interior_ptr(T, self._obj, [offset])
+ else:
+ val = _ptr(Ptr(T), val, solid=self._solid)
+ return val
+
assert not '__dict__' in dir(_ptr)
+class _interior_ptr(_abstract_ptr):
+ __slots__ = ('_parent', '_offsets')
+ def _set_parent(self, _parent):
+ _interior_ptr._parent.__set__(self, _parent)
+ def _set_offsets(self, _offsets):
+ _interior_ptr._offsets.__set__(self, _offsets)
+
+ def __init__(self, _T, _parent, _offsets):
+ self._set_T(_T)
+ #self._set_parent(weakref.ref(_parent))
+ self._set_parent(_parent)
+ self._set_offsets(_offsets)
+
+ def __nonzero__(self):
+ raise RuntimeError, "do not test an interior pointer for nullity"
+
+ def _get_obj(self):
+ ob = self._parent
+ if ob is None:
+ raise RuntimeError
+ if isinstance(ob, _container):
+ ob._check()
+ for o in self._offsets:
+ if isinstance(o, str):
+ ob = ob._getattr(o)
+ else:
+ ob = ob.getitem(o)
+ return ob
+ _obj = property(_get_obj)
+
+ def _get_TYPE(self):
+ ob = self._parent
+ if ob is None:
+ raise RuntimeError
+ return InteriorPtr(typeOf(ob), self._T, self._offsets)
+## _TYPE = property(_get_TYPE)
+
+ def _expose(self, offset, val):
+ """XXX A nice docstring here"""
+ T = typeOf(val)
+ if isinstance(T, ContainerType):
+ assert T._gckind == 'raw'
+ val = _interior_ptr(T, self._parent, self._offsets + [offset])
+ return val
+
+
+
+assert not '__dict__' in dir(_interior_ptr)
+
class _container(object):
__slots__ = ()
def _parentstructure(self):
Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/opimpl.py
==============================================================================
--- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/opimpl.py (original)
+++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/opimpl.py Wed Sep 13 11:50:52 2006
@@ -126,6 +126,27 @@
lltype.ContainerType)
return getattr(obj, field)
+def op_getinteriorfield(obj, *offsets):
+ checkptr(obj)
+ ob = obj
+ for o in offsets:
+ if isinstance(o, str):
+ ob = getattr(ob, o)
+ else:
+ ob = ob[o]
+ assert not isinstance(ob, lltype._interior_ptr)
+ return ob
+
+def op_getinteriorarraysize(obj, *offsets):
+ checkptr(obj)
+ ob = obj
+ for o in offsets:
+ if isinstance(o, str):
+ ob = getattr(ob, o)
+ else:
+ ob = ob[o]
+ return len(ob)
+
def op_getarraysubstruct(array, index):
checkptr(array)
result = array[index]
Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/rdict.py
==============================================================================
--- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/rdict.py (original)
+++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/rdict.py Wed Sep 13 11:50:52 2006
@@ -75,7 +75,7 @@
# compute the shape of the DICTENTRY structure
entryfields = []
- entrymeths = {
+ adtmeths = {
'must_clear_key': (isinstance(self.DICTKEY, lltype.Ptr)
and self.DICTKEY._needsgc()),
'must_clear_value': (isinstance(self.DICTVALUE, lltype.Ptr)
@@ -93,37 +93,41 @@
nullkeymarker = not self.key_repr.can_ll_be_null(s_key)
nullvaluemarker = not self.value_repr.can_ll_be_null(s_value)
+ adtmeths['entry_has_f_everused'] = 0
if nullkeymarker:
- entrymeths['everused'] = ll_everused_from_key
+ adtmeths['entry_everused'] = ll_everused_from_key
elif nullvaluemarker:
- entrymeths['everused'] = ll_everused_from_value
+ adtmeths['entry_everused'] = ll_everused_from_value
else:
entryfields.append(("f_everused", lltype.Bool))
- entrymeths['everused'] = ll_everused_from_flag
+ adtmeths['entry_everused'] = ll_everused_from_flag
+ adtmeths['entry_has_f_everused'] = 1
# * if the key or the value can also contain a "dummy" non-null
# marker, we use it for deleted entries.
rtyper = self.rtyper
dummy_obj = self.key_repr.get_ll_dummyval_obj(rtyper, s_key)
+ adtmeths['entry_has_f_valid'] = 0
if dummy_obj:
- entrymeths['dummy_obj'] = dummy_obj
- entrymeths['valid'] = ll_valid_from_key
- entrymeths['mark_deleted'] = ll_mark_deleted_in_key
+ adtmeths['dummy_obj'] = dummy_obj
+ adtmeths['entry_valid'] = ll_valid_from_key
+ adtmeths['mark_entry_deleted'] = ll_mark_deleted_in_key
# the key is overwritten by 'dummy' when the entry is deleted
- entrymeths['must_clear_key'] = False
+ adtmeths['must_clear_key'] = False
else:
dummy_obj = self.value_repr.get_ll_dummyval_obj(rtyper,
s_value)
if dummy_obj:
- entrymeths['dummy_obj'] = dummy_obj
- entrymeths['valid'] = ll_valid_from_value
- entrymeths['mark_deleted'] = ll_mark_deleted_in_value
+ adtmeths['dummy_obj'] = dummy_obj
+ adtmeths['entry_valid'] = ll_valid_from_value
+ adtmeths['mark_entry_deleted'] = ll_mark_deleted_in_value
# value is overwritten by 'dummy' when entry is deleted
- entrymeths['must_clear_value'] = False
+ adtmeths['must_clear_value'] = False
else:
entryfields.append(("f_valid", lltype.Bool))
- entrymeths['valid'] = ll_valid_from_flag
- entrymeths['mark_deleted'] = ll_mark_deleted_in_flag
+ adtmeths['entry_has_f_valid'] = 1
+ adtmeths['entry_valid'] = ll_valid_from_flag
+ adtmeths['mark_entry_deleted'] = ll_mark_deleted_in_flag
# * the value
entryfields.append(("value", self.DICTVALUE))
@@ -133,15 +137,18 @@
fasthashfn = None
else:
fasthashfn = self.key_repr.get_ll_fasthash_function()
+
+ adtmeths['entry_has_f_hash'] = 0
if fasthashfn is None:
entryfields.append(("f_hash", lltype.Signed))
- entrymeths['hash'] = ll_hash_from_cache
+ adtmeths['entry_has_f_hash'] = 1
+ adtmeths['hash'] = ll_hash_from_cache
else:
- entrymeths['hash'] = ll_hash_recomputed
- entrymeths['fasthashfn'] = fasthashfn
+ adtmeths['hash'] = ll_hash_recomputed
+ adtmeths['fasthashfn'] = fasthashfn
# Build the lltype data structures
- self.DICTENTRY = lltype.Struct("dictentry", adtmeths=entrymeths,
+ self.DICTENTRY = lltype.Struct("dictentry", #adtmeths=entrymeths,
*entryfields)
self.DICTENTRYARRAY = lltype.GcArray(self.DICTENTRY)
fields = [ ("num_items", lltype.Signed),
@@ -151,13 +158,13 @@
self.r_rdict_eqfn, self.r_rdict_hashfn = self._custom_eq_hash_repr()
fields.extend([ ("fnkeyeq", self.r_rdict_eqfn.lowleveltype),
("fnkeyhash", self.r_rdict_hashfn.lowleveltype) ])
- adtmeths = {
+ adtmeths.update({
'keyhash': ll_keyhash_custom,
'keyeq': ll_keyeq_custom,
'r_rdict_eqfn': self.r_rdict_eqfn,
'r_rdict_hashfn': self.r_rdict_hashfn,
'paranoia': True,
- }
+ })
else:
# figure out which functions must be used to hash and compare
ll_keyhash = self.key_repr.get_ll_hash_function()
@@ -165,11 +172,11 @@
ll_keyhash = lltype.staticAdtMethod(ll_keyhash)
if ll_keyeq is not None:
ll_keyeq = lltype.staticAdtMethod(ll_keyeq)
- adtmeths = {
+ adtmeths.update({
'keyhash': ll_keyhash,
'keyeq': ll_keyeq,
'paranoia': False,
- }
+ })
self.DICT.become(lltype.GcStruct("dicttable", adtmeths=adtmeths,
*fields))
@@ -331,47 +338,47 @@
# be direct_call'ed from rtyped flow graphs, which means that they will
# get flowed and annotated, mostly with SomePtr.
-def ll_everused_from_flag(entry):
- return entry.f_everused
+def ll_everused_from_flag(d, i):
+ return d.entries[i].f_everused
-def ll_everused_from_key(entry):
- return bool(entry.key)
+def ll_everused_from_key(d, i):
+ return bool(d.entries[i].key)
-def ll_everused_from_value(entry):
- return bool(entry.value)
+def ll_everused_from_value(d, i):
+ return bool(d.entries[i].value)
-def ll_valid_from_flag(entry):
- return entry.f_valid
-
-def ll_mark_deleted_in_flag(entry):
- entry.f_valid = False
-
-def ll_valid_from_key(entry):
- ENTRY = lltype.typeOf(entry).TO
- dummy = ENTRY.dummy_obj.ll_dummy_value
- return entry.everused() and entry.key != dummy
-
-def ll_mark_deleted_in_key(entry):
- ENTRY = lltype.typeOf(entry).TO
- dummy = ENTRY.dummy_obj.ll_dummy_value
- entry.key = dummy
-
-def ll_valid_from_value(entry):
- ENTRY = lltype.typeOf(entry).TO
- dummy = ENTRY.dummy_obj.ll_dummy_value
- return entry.everused() and entry.value != dummy
-
-def ll_mark_deleted_in_value(entry):
- ENTRY = lltype.typeOf(entry).TO
- dummy = ENTRY.dummy_obj.ll_dummy_value
- entry.value = dummy
-
-def ll_hash_from_cache(entry):
- return entry.f_hash
-
-def ll_hash_recomputed(entry):
- ENTRY = lltype.typeOf(entry).TO
- return ENTRY.fasthashfn(entry.key)
+def ll_valid_from_flag(d, i):
+ return d.entries[i].f_valid
+
+def ll_mark_deleted_in_flag(d, i):
+ d.entries[i].f_valid = False
+
+def ll_valid_from_key(d, i):
+ DICT = lltype.typeOf(d).TO
+ dummy = DICT.dummy_obj.ll_dummy_value
+ return d.entry_everused(i) and d.entries[i].key != dummy
+
+def ll_mark_deleted_in_key(d, i):
+ DICT = lltype.typeOf(d).TO
+ dummy = DICT.dummy_obj.ll_dummy_value
+ d.entries[i].key = dummy
+
+def ll_valid_from_value(d, i):
+ DICT = lltype.typeOf(d).TO
+ dummy = DICT.dummy_obj.ll_dummy_value
+ return d.entry_everused(i) and d.entries[i].value != dummy
+
+def ll_mark_deleted_in_value(d, i):
+ DICT = lltype.typeOf(d).TO
+ dummy = DICT.dummy_obj.ll_dummy_value
+ d.entries[i].value = dummy
+
+def ll_hash_from_cache(d, i):
+ return d.entries[i].f_hash
+
+def ll_hash_recomputed(d, i):
+ DICT = lltype.typeOf(d).TO
+ return DICT.fasthashfn(d.entries[i].key)
def ll_keyhash_custom(d, key):
DICT = lltype.typeOf(d).TO
@@ -389,28 +396,29 @@
return bool(d) and d.num_items != 0
def ll_dict_getitem(d, key):
- entry = ll_dict_lookup(d, key, d.keyhash(key))
- if entry.valid():
- return entry.value
+ i = ll_dict_lookup(d, key, d.keyhash(key))
+ if d.entry_valid(i):
+ return d.entries[i].value
else:
raise KeyError
def ll_dict_setitem(d, key, value):
hash = d.keyhash(key)
- entry = ll_dict_lookup(d, key, hash)
- everused = entry.everused()
- valid = entry.valid()
+ i = ll_dict_lookup(d, key, hash)
+ entry = d.entries[i]
+ everused = d.entry_everused(i)
+ valid = d.entry_valid(i)
# set up the new entry
- ENTRY = lltype.typeOf(entry).TO
+ DICT = lltype.typeOf(d).TO
entry.value = value
if valid:
return
entry.key = key
- if hasattr(ENTRY, 'f_hash'): entry.f_hash = hash
- if hasattr(ENTRY, 'f_valid'): entry.f_valid = True
+ if DICT.entry_has_f_hash: entry.f_hash = hash
+ if DICT.entry_has_f_valid: entry.f_valid = True
d.num_items += 1
if not everused:
- if hasattr(ENTRY, 'f_everused'): entry.f_everused = True
+ if DICT.entry_has_f_everused: entry.f_everused = True
d.num_pristine_entries -= 1
if d.num_pristine_entries <= len(d.entries) / 3:
ll_dict_resize(d)
@@ -421,53 +429,77 @@
# the dict contains no deleted entries. This routine has the advantage
# of never calling d.keyhash() and d.keyeq(), so it cannot call back
# to user code. ll_dict_insertclean() doesn't resize the dict, either.
- entry = ll_dict_lookup_clean(d, hash)
- ENTRY = lltype.typeOf(entry).TO
+ entry = d.entries[ll_dict_lookup_clean(d, hash)]
+ DICT = lltype.typeOf(d).TO
entry.value = value
entry.key = key
- if hasattr(ENTRY, 'f_hash'): entry.f_hash = hash
- if hasattr(ENTRY, 'f_valid'): entry.f_valid = True
- if hasattr(ENTRY, 'f_everused'): entry.f_everused = True
+ if DICT.entry_has_f_hash: entry.f_hash = hash
+ if DICT.entry_has_f_valid: entry.f_valid = True
+ if DICT.entry_has_f_everused: entry.f_everused = True
d.num_items += 1
d.num_pristine_entries -= 1
def ll_dict_delitem(d, key):
- entry = ll_dict_lookup(d, key, d.keyhash(key))
- if not entry.valid():
+ i = ll_dict_lookup(d, key, d.keyhash(key))
+ if not d.entry_valid(i):
raise KeyError
- entry.mark_deleted()
+ entry = d.entries[i]
+ d.mark_entry_deleted(i)
d.num_items -= 1
# clear the key and the value if they are GC pointers
- ENTRY = lltype.typeOf(entry).TO
- if ENTRY.must_clear_key:
+ DICT = lltype.typeOf(d).TO
+ if DICT.must_clear_key:
key = entry.key # careful about destructor side effects:
# keep key alive until entry.value has also
# been zeroed (if it must be)
- entry.key = lltype.nullptr(ENTRY.key.TO)
- if ENTRY.must_clear_value:
- entry.value = lltype.nullptr(ENTRY.value.TO)
+ entry.key = lltype.nullptr(DICT.entries.OF.key.TO)
+ if DICT.must_clear_value:
+ entry.value = lltype.nullptr(DICT.entries.OF.value.TO)
num_entries = len(d.entries)
if num_entries > DICT_INITSIZE and d.num_items < num_entries / 4:
ll_dict_resize(d)
def ll_dict_resize(d):
old_entries = d.entries
- old_size = len(old_entries)
+ old_size = len(old_entries)
# make a 'new_size' estimate and shrink it if there are many
# deleted entry markers
new_size = old_size * 2
while new_size > DICT_INITSIZE and d.num_items < new_size / 4:
new_size /= 2
- d.entries = lltype.malloc(lltype.typeOf(old_entries).TO, new_size, zero=True)
- d.num_items = 0
- d.num_pristine_entries = new_size
+ new_entries = lltype.malloc(lltype.typeOf(d).TO.entries.TO, new_size, zero=True)
+ new_num_items = 0
+ new_num_pristine_entries = new_size
i = 0
while i < old_size:
- entry = old_entries[i]
- if entry.valid():
- ll_dict_insertclean(d, entry.key, entry.value, entry.hash())
+ entry = d.entries[i]
+ if d.entry_valid(i):
+
+ # AAAAAAAAAAA
+ hash = d.hash(i)
+
+ old_entries = d.entries
+ old_num_items = d.num_items
+ old_num_pristine_entries = d.num_pristine_entries
+ d.entries = new_entries
+ d.num_items = new_num_items
+ d.num_pristine_entries = new_num_pristine_entries
+
+ ll_dict_insertclean(d, entry.key, entry.value, hash)
+
+ new_entries = d.entries
+ new_num_items = d.num_items
+ new_num_pristine_entries = d.num_pristine_entries
+ d.entries = old_entries
+ d.num_items = old_num_items
+ d.num_pristine_entries = old_num_pristine_entries
+
i += 1
+ d.entries = new_entries
+ d.num_items = new_num_items
+ d.num_pristine_entries = new_num_pristine_entries
+
# ------- a port of CPython's dictobject.c's lookdict implementation -------
PERTURB_SHIFT = 5
@@ -478,26 +510,28 @@
i = r_uint(hash & mask)
# do the first try before any looping
entry = entries[i]
- if entry.valid():
+ found_freeslot = False
+ freeslot_index = r_uint(0)
+ if d.entry_valid(i):
checkingkey = entry.key
if checkingkey == key:
- return entry # found the entry
- if d.keyeq is not None and entry.hash() == hash:
+ return i # found the entry
+ if d.keyeq is not None and d.hash(i) == hash:
# correct hash, maybe the key is e.g. a different pointer to
# an equal object
found = d.keyeq(checkingkey, key)
if DICT.paranoia:
if (entries != d.entries or
- not entry.valid() or entry.key != checkingkey):
+ not d.entry_valid(i) or entry.key != checkingkey):
# the compare did major nasty stuff to the dict: start over
return ll_dict_lookup(d, key, hash)
if found:
- return entry # found the entry
- freeslot = lltype.nullptr(lltype.typeOf(entry).TO)
- elif entry.everused():
- freeslot = entry
+ return i # found the entry
+ elif d.entry_everused(i):
+ freeslot_index = i
+ found_freeslot = True
else:
- return entry # pristine entry -- lookup failed
+ return i # pristine entry -- lookup failed
# In the loop, a deleted entry (everused and not valid) is by far
# (factor of 100s) the least likely outcome, so test for that last.
@@ -505,26 +539,30 @@
while 1:
i = ((i << 2) + i + perturb + 1) & mask
entry = entries[i]
- if not entry.everused():
- return freeslot or entry
- elif entry.valid():
+ if not d.entry_everused(i):
+ if found_freeslot:
+ return freeslot_index
+ else:
+ return i
+ elif d.entry_valid(i):
checkingkey = entry.key
if checkingkey == key:
- return entry
- if d.keyeq is not None and entry.hash() == hash:
+ return i
+ if d.keyeq is not None and d.hash(i) == hash:
# correct hash, maybe the key is e.g. a different pointer to
# an equal object
found = d.keyeq(checkingkey, key)
if DICT.paranoia:
if (entries != d.entries or
- not entry.valid() or entry.key != checkingkey):
+ not d.entry_valid(i) or entry.key != checkingkey):
# the compare did major nasty stuff to the dict:
# start over
return ll_dict_lookup(d, key, hash)
if found:
- return entry # found the entry
- elif not freeslot:
- freeslot = entry
+ return i
+ elif not found_freeslot:
+ freeslot_index = i
+ found_freeslot = True
perturb >>= PERTURB_SHIFT
def ll_dict_lookup_clean(d, hash):
@@ -536,11 +574,11 @@
i = r_uint(hash & mask)
entry = entries[i]
perturb = r_uint(hash)
- while entry.everused():
+ while d.entry_everused(i):
i = ((i << 2) + i + perturb + 1) & mask
entry = entries[i]
perturb >>= PERTURB_SHIFT
- return entry
+ return i
# ____________________________________________________________
#
@@ -614,8 +652,9 @@
entries_len = len(entries)
while index < entries_len:
entry = entries[index]
+ i = index
index = index + 1
- if entry.valid():
+ if dict.entry_valid(i):
iter.index = index
if RETURNTYPE is lltype.Void:
return None
@@ -625,6 +664,9 @@
r.item1 = recast(RETURNTYPE.TO.item1, entry.value)
return r
elif func is dum_keys:
+ from pypy.rpython.lltypesystem.lloperation import llop
+ from pypy.rpython.lltypesystem.lltype import Void
+ llop.debug_print(Void, entry.key)
return entry.key
elif func is dum_values:
return entry.value
@@ -636,16 +678,16 @@
# methods
def ll_get(dict, key, default):
- entry = ll_dict_lookup(dict, key, dict.keyhash(key))
- if entry.valid():
- return entry.value
+ i = ll_dict_lookup(dict, key, dict.keyhash(key))
+ if dict.entry_valid(i):
+ return dict.entries[i].value
else:
return default
def ll_setdefault(dict, key, default):
- entry = ll_dict_lookup(dict, key, dict.keyhash(key))
- if entry.valid():
- return entry.value
+ i = ll_dict_lookup(dict, key, dict.keyhash(key))
+ if dict.entry_valid(i):
+ return dict.entries[i].value
else:
ll_dict_setitem(dict, key, default)
return default
@@ -663,12 +705,12 @@
while i < dictsize:
d_entry = d.entries[i]
entry = dict.entries[i]
- ENTRY = lltype.typeOf(entry).TO
+ DICT = lltype.typeOf(dict).TO
d_entry.key = entry.key
- if hasattr(ENTRY, 'f_valid'): d_entry.f_valid = entry.f_valid
- if hasattr(ENTRY, 'f_everused'): d_entry.f_everused = entry.f_everused
+ if DICT.entry_has_f_valid: d_entry.f_valid = entry.f_valid
+ if DICT.entry_has_f_everused: d_entry.f_everused = entry.f_everused
d_entry.value = entry.value
- if hasattr(ENTRY, 'f_hash'): d_entry.f_hash = entry.f_hash
+ if DICT.entry_has_f_hash: d_entry.f_hash = entry.f_hash
i += 1
return d
@@ -686,7 +728,7 @@
i = 0
while i < d2len:
entry = entries[i]
- if entry.valid():
+ if dic2.entry_valid(i):
ll_dict_setitem(dic1, entry.key, entry.value)
i += 1
@@ -710,7 +752,7 @@
p = 0
while i < dlen:
entry = entries[i]
- if entry.valid():
+ if dic.entry_valid(i):
ELEM = lltype.typeOf(items).TO.OF
if ELEM is not lltype.Void:
if func is dum_items:
@@ -727,5 +769,5 @@
return res
def ll_contains(d, key):
- entry = ll_dict_lookup(d, key, d.keyhash(key))
- return entry.valid()
+ i = ll_dict_lookup(d, key, d.keyhash(key))
+ return d.entry_valid(i)
Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/rstr.py (original)
+++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/rstr.py Wed Sep 13 11:50:52 2006
@@ -85,10 +85,7 @@
cstr = inputconst(Void, STR)
v_result = llops.genop('malloc_varsize', [cstr, v_len],
resulttype=Ptr(STR))
- cchars = inputconst(Void, "chars")
- v_chars = llops.genop('getsubstruct', [v_result, cchars],
- resulttype=Ptr(STR.chars))
- llops.gencapicall('PyString_ToLLCharArray', [v, v_chars])
+ llops.gencapicall('PyString_ToRPyString', [v, v_result])
string_repr = llops.rtyper.type_system.rstr.string_repr
v_result = llops.convertvar(v_result, string_repr, r_to)
return v_result
@@ -99,15 +96,11 @@
string_repr = llops.rtyper.type_system.rstr.string_repr
v = llops.convertvar(v, r_from, string_repr)
cchars = inputconst(Void, "chars")
- v_chars = llops.genop('getsubstruct', [v, cchars],
- resulttype=Ptr(STR.chars))
- v_size = llops.genop('getarraysize', [v_chars],
- resulttype=Signed)
# xxx put in table
- return llops.gencapicall('PyString_FromLLCharArrayAndSize',
- [v_chars, v_size],
+ return llops.gencapicall('PyString_FromRPyString',
+ [v],
resulttype=pyobj_repr,
- _callable= lambda chars, sz: pyobjectptr(''.join(chars)))
+ _callable= lambda v: pyobjectptr(''.join(v.chars)))
def mallocstr(length):
r = malloc(STR, length)
Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/test/test_lltype.py
==============================================================================
--- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/test/test_lltype.py (original)
+++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/test/test_lltype.py Wed Sep 13 11:50:52 2006
@@ -1,7 +1,5 @@
from pypy.rpython.lltypesystem.lltype import *
-
-def isweak(p, T):
- return p._weak and typeOf(p).TO == T
+import py
def test_basics():
S0 = GcStruct("s0", ('a', Signed), ('b', Signed))
@@ -24,7 +22,7 @@
x = malloc(Ar,3)
print x
assert typeOf(x) == Ptr(Ar)
- assert isweak(x[0], Ar.OF)
+ py.test.raises(TypeError, "typeOf(x[0])")
x[0].v = 1
x[1].v = 2
x[2].v = 3
@@ -94,9 +92,7 @@
s1 = malloc(S1, 4)
s1.a = 0
assert s1.a == 0
- assert isweak(s1.rest, S1.rest)
assert len(s1.rest) == 4
- assert isweak(s1.rest[0], S1.rest.OF)
s1.rest[0].v = 0
assert typeOf(s1.rest[0].v) == Signed
assert s1.rest[0].v == 0
@@ -118,11 +114,13 @@
S2 = Struct("s2", ('s3', S3))
S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2))
p1 = malloc(S1)
- assert isweak(p1.sub1, S2)
- assert isweak(p1.sub2, S2)
- assert isweak(p1.sub1.s3, S3)
+ py.test.raises(TypeError, "typeOf(p1.sub1)")
+ # _T isn't really a public API, but there's not much else to test.
+ assert p1.sub1._T == S2
+ assert p1.sub2._T == S2
+ assert p1.sub1.s3._T == S3
p2 = p1.sub1
- assert isweak(p2.s3, S3)
+ assert p2.s3._T == S3
def test_gc_substructure_ptr():
S1 = GcStruct("s2", ('a', Signed))
@@ -130,7 +128,7 @@
S0 = GcStruct("s1", ('sub1', S1), ('sub2', S2))
p1 = malloc(S0)
assert typeOf(p1.sub1) == Ptr(S1)
- assert isweak(p1.sub2, S2)
+ py.test.raises(TypeError, "typeOf(p1.sub2)")
def test_cast_simple_widening():
S2 = Struct("s2", ('a', Signed))
@@ -202,6 +200,7 @@
py.test.raises(RuntimeError, "cast_pointer(Ptr(S1), p3)")
def test_best_effort_gced_parent_detection():
+ py.test.skip("test not relevant any more")
S2 = Struct("s2", ('a', Signed))
S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2), ('tail', Array(('e', Signed))))
p1 = malloc(S1, 1)
@@ -216,6 +215,7 @@
py.test.raises(RuntimeError, "p3[0]")
def test_best_effort_gced_parent_for_arrays():
+ py.test.skip("test not relevant any more")
A1 = GcArray(('v', Signed))
p1 = malloc(A1, 10)
p1[5].v=3
@@ -422,6 +422,8 @@
assert runtime_type_info(s1.sub) == getRuntimeTypeInfo(S1)
def test_flavor_malloc():
+ def isweak(p, T):
+ return p._weak and typeOf(p).TO == T
S = Struct('s', ('x', Signed))
py.test.raises(TypeError, malloc, S)
p = malloc(S, flavor="raw")
Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/test/test_picklelltype.py
==============================================================================
--- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/test/test_picklelltype.py (original)
+++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/test/test_picklelltype.py Wed Sep 13 11:50:52 2006
@@ -1,9 +1,6 @@
from pypy.rpython.lltypesystem.lltype import *
-import pickle
-
-def isweak(p, T):
- return p._weak and typeOf(p).TO == T
+import pickle, py
def test_pickle_types():
S0 = GcStruct("s0", ('a', Signed), ('b', Signed))
@@ -33,7 +30,6 @@
p_x = pickle.dumps(x)
r_x = pickle.loads(p_x)
assert typeOf(x) == Ptr(Ar)
- assert isweak(x[0], Ar.OF)
assert typeOf(x[0].v) == Signed
assert [x[z].v for z in range(3)] == [1, 2, 3]
#
@@ -98,9 +94,7 @@
p_s1 = pickle.dumps(s1)
r_s1 = pickle.loads(p_s1)
assert r_s1.a == 0
- assert isweak(r_s1.rest, S1.rest)
assert len(r_s1.rest) == 4
- assert isweak(r_s1.rest[0], S1.rest.OF)
assert typeOf(r_s1.rest[0].v) == Signed
assert r_s1.rest[0].v == 0
py.test.raises(IndexError, "r_s1.rest[4]")
@@ -120,11 +114,13 @@
p1 = malloc(S1)
p_p1 = pickle.dumps(p1)
r_p1 = pickle.loads(p_p1)
- assert isweak(r_p1.sub1, S2)
- assert isweak(r_p1.sub2, S2)
- assert isweak(r_p1.sub1.s3, S3)
+ py.test.raises(TypeError, "typeOf(p1.sub1)")
+ # _T isn't really a public API, but there's not much else to test.
+ assert r_p1.sub1._T == S2
+ assert r_p1.sub2._T == S2
+ assert r_p1.sub1.s3._T == S3
r_p2 = r_p1.sub1
- assert isweak(r_p2.s3, S3)
+ assert r_p2.s3._T == S3
def test_gc_substructure_ptr():
S1 = GcStruct("s2", ('a', Signed))
@@ -133,7 +129,7 @@
p1 = malloc(S0)
r_p1 = pickle.loads(pickle.dumps(p1))
assert typeOf(r_p1.sub1) == Ptr(S1)
- assert isweak(r_p1.sub2, S2)
+ py.test.raises(TypeError, "typeOf(r_p1.sub2)")
def test_cast_simple_widening():
S2 = Struct("s2", ('a', Signed))
@@ -148,6 +144,7 @@
assert p4 == r_p1
def test_best_effort_gced_parent_detection():
+ py.test.skip("test not relevant any more")
S2 = Struct("s2", ('a', Signed))
S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2), ('tail', Array(('e', Signed))))
p1 = malloc(S1, 1)
@@ -167,6 +164,7 @@
py.test.raises(RuntimeError, "r_p3[0]")
def test_best_effort_gced_parent_for_arrays():
+ py.test.skip("test not relevant any more")
A1 = GcArray(('v', Signed))
p1 = malloc(A1, 10)
for i in range(10):
@@ -340,6 +338,8 @@
assert runtime_type_info(s1.sub) == getRuntimeTypeInfo(S1)
def test_flavor_malloc():
+ def isweak(p, T):
+ return p._weak and typeOf(p).TO == T
S = Struct('s', ('x', Signed))
py.test.raises(TypeError, malloc, S)
p = malloc(S, flavor="raw")
Modified: pypy/branch/kill-keepalives/pypy/rpython/memory/convertlltype.py
==============================================================================
--- pypy/branch/kill-keepalives/pypy/rpython/memory/convertlltype.py (original)
+++ pypy/branch/kill-keepalives/pypy/rpython/memory/convertlltype.py Wed Sep 13 11:50:52 2006
@@ -34,7 +34,7 @@
self.query_types = qt
def convert(self, val_or_ptr, inline_to_ptr=None):
- TYPE = lltype.typeOf(val_or_ptr)
+ TYPE = lltype.rawTypeOf(val_or_ptr)
if isinstance(TYPE, lltype.Primitive):
assert inline_to_ptr is None
return get_real_value(val_or_ptr)
@@ -58,7 +58,7 @@
ptr = self.converted[_array]
assert inline_to_ptr is None or ptr == inline_to_ptr
return ptr
- TYPE = lltype.typeOf(_array)
+ TYPE = lltype.rawTypeOf(_array)
arraylength = len(_array.items)
size = sizeof(TYPE, arraylength)
if inline_to_ptr is not None:
@@ -95,7 +95,7 @@
return getattr(ptr, _struct._parent_index)
else:
return ptr[_struct._parent_index]
- TYPE = lltype.typeOf(_struct)
+ TYPE = lltype.rawTypeOf(_struct)
if TYPE._arrayfld is not None:
inlinedarraylength = len(getattr(_struct, TYPE._arrayfld).items)
size = sizeof(TYPE, inlinedarraylength)
@@ -127,7 +127,7 @@
def convert_pointer(self, _ptr, inline_to_ptr):
assert inline_to_ptr is None, "can't inline pointer"
- TYPE = lltype.typeOf(_ptr)
+ TYPE = lltype.rawTypeOf(_ptr)
if _ptr._obj is not None:
return self.convert(_ptr._obj)
else:
@@ -135,7 +135,7 @@
def convert_object(self, _obj, inline_to_ptr):
assert inline_to_ptr is None, "can't inline function or pyobject"
- return simulatorptr(lltype.Ptr(lltype.typeOf(_obj)),
+ return simulatorptr(lltype.Ptr(lltype.rawTypeOf(_obj)),
lladdress.get_address_of_object(_obj))
def collect_constants_and_types(graphs):
constants = {}
@@ -190,7 +190,7 @@
continue
elif isinstance(cand, str):
continue
- elif isinstance(lltype.typeOf(cand), lltype.Primitive):
+ elif isinstance(lltype.rawTypeOf(cand), lltype.Primitive):
continue
elif cand in seen:
continue
Modified: pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py (original)
+++ pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py Wed Sep 13 11:50:52 2006
@@ -258,28 +258,18 @@
raise NotImplementedError("gc_protect does not make sense for this gc")
def replace_setfield(self, op, livevars, block):
- if not var_ispyobj(op.args[2]):
- return [op]
- oldval = varoftype(op.args[2].concretetype)
- getoldvalop = SpaceOperation("getfield",
- [op.args[0], op.args[1]], oldval)
- result = [getoldvalop]
- result.extend(self.push_alive(op.args[2]))
- result.append(op)
- result.extend(self.pop_alive(oldval))
- return result
-
- def replace_setarrayitem(self, op, livevars, block):
- if not var_ispyobj(op.args[2]):
- return [op]
- oldval = varoftype(op.args[2].concretetype)
- getoldvalop = SpaceOperation("getarrayitem",
- [op.args[0], op.args[1]], oldval)
- result = [getoldvalop]
- result.extend(self.push_alive(op.args[2]))
- result.append(op)
+ if not var_ispyobj(op.args[-1]):
+ return [SpaceOperation("bare_" + op.opname, op.args, op.result)]
+ oldval = varoftype(op.args[-1].concretetype)
+ result = []
+ result.append(SpaceOperation("g" + op.opname[1:],
+ op.args[:-1], oldval))
+ result.extend(self.push_alive(op.args[-1]))
+ result.append(SpaceOperation("bare_" + op.opname, op.args, op.result))
result.extend(self.pop_alive(oldval))
return result
+ replace_setinteriorfield = replace_setfield
+ replace_setarrayitem = replace_setfield
def replace_safe_call(self, op, livevars, block):
return [SpaceOperation("direct_call", op.args, op.result)]
@@ -502,29 +492,20 @@
newops[-1].result = op.result
return newops
- def replace_setfield(self, op, livevars, block):
- if not var_needsgc(op.args[2]):
- return [op]
- oldval = varoftype(op.args[2].concretetype)
- getoldvalop = SpaceOperation("getfield",
- [op.args[0], op.args[1]], oldval)
- result = [getoldvalop]
- result.extend(self.push_alive(op.args[2]))
- result.append(op)
- result.extend(self.pop_alive(oldval))
- return result
- def replace_setarrayitem(self, op, livevars, block):
- if not var_needsgc(op.args[2]):
- return [op]
- oldval = varoftype(op.args[2].concretetype)
- getoldvalop = SpaceOperation("getarrayitem",
- [op.args[0], op.args[1]], oldval)
- result = [getoldvalop]
- result.extend(self.push_alive(op.args[2]))
- result.append(op)
+ def replace_setfield(self, op, livevars, block):
+ if not var_needsgc(op.args[-1]):
+ return [SpaceOperation("bare_" + op.opname, op.args, op.result)]
+ oldval = varoftype(op.args[-1].concretetype)
+ result = []
+ result.append(SpaceOperation("g" + op.opname[1:],
+ op.args[:-1], oldval))
+ result.extend(self.push_alive(op.args[-1]))
+ result.append(SpaceOperation("bare_" + op.opname, op.args, op.result))
result.extend(self.pop_alive(oldval))
return result
+ replace_setinteriorfield = replace_setfield
+ replace_setarrayitem = replace_setfield
## -- maybe add this for tests and for consistency --
## def consider_constant(self, TYPE, value):
@@ -1349,10 +1330,15 @@
c_null = Constant(lltype.nullptr(FIELD.TO), FIELD)
llops.genop('bare_setfield', [v, c_name, c_null])
elif isinstance(FIELD, lltype.Struct):
- c_name = Constant(name, lltype.Void)
- v1 = llops.genop('getsubstruct', [v, c_name],
- resulttype = lltype.Ptr(FIELD))
- gen_zero_gc_pointers(FIELD, v1, llops)
+ # XXX this is insufficient!
+ for name2 in FIELD._names:
+ FIELD_TYPE = getattr(FIELD, name2)
+ if isinstance(FIELD_TYPE, lltype.Ptr) and FIELD_TYPE._needsgc():
+ c_name = Constant(name, lltype.Void)
+ v1 = llops.genop('getsubstruct', [v, c_name],
+ resulttype = lltype.Ptr(FIELD))
+ gen_zero_gc_pointers(FIELD, v1, llops)
+ break
# ____________________________________________________________
Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py
==============================================================================
--- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py (original)
+++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py Wed Sep 13 11:50:52 2006
@@ -266,8 +266,8 @@
def reccopy(source, dest):
# copy recursively a structure or array onto another.
- T = lltype.typeOf(source).TO
- assert T == lltype.typeOf(dest).TO
+ T = lltype.rawTypeOf(source).TO
+ assert T == lltype.rawTypeOf(dest).TO
if isinstance(T, (lltype.Array, lltype.FixedSizeArray)):
assert len(source) == len(dest)
ITEMTYPE = T.OF
@@ -295,7 +295,7 @@
raise TypeError(T)
def reccopy_arrayitem(source, destarray, destindex):
- ITEMTYPE = lltype.typeOf(destarray).TO.OF
+ ITEMTYPE = lltype.rawTypeOf(destarray).TO.OF
if isinstance(ITEMTYPE, lltype.Primitive):
destarray[destindex] = source
else:
Modified: pypy/branch/kill-keepalives/pypy/rpython/rptr.py
==============================================================================
--- pypy/branch/kill-keepalives/pypy/rpython/rptr.py (original)
+++ pypy/branch/kill-keepalives/pypy/rpython/rptr.py Wed Sep 13 11:50:52 2006
@@ -2,7 +2,8 @@
from pypy.annotation import model as annmodel
from pypy.objspace.flow import model as flowmodel
from pypy.rpython.lltypesystem.lltype import \
- Ptr, ContainerType, Void, Signed, Bool, FuncType, typeOf, FixedSizeArray
+ Ptr, ContainerType, Void, Signed, Bool, FuncType, typeOf, FixedSizeArray, \
+ InteriorPtr, OpaqueType
from pypy.rpython.error import TyperError
from pypy.rpython.rmodel import Repr, IntegerRepr
@@ -19,6 +20,9 @@
## else:
return self.__class__, self.ll_ptrtype
+class __extend__(annmodel.SomeInteriorPtr):
+ def rtyper_makerepr(self, rtyper):
+ return InteriorPtrRepr(self.ll_ptrtype)
class PtrRepr(Repr):
@@ -32,7 +36,11 @@
return hop.inputarg(hop.r_result, arg=0)
FIELD_TYPE = getattr(self.lowleveltype.TO, attr)
if isinstance(FIELD_TYPE, ContainerType):
- newopname = 'getsubstruct'
+ if isinstance(hop.r_result, InteriorPtrRepr):
+ return hop.genop('same_as', [hop.inputarg(self, 0)],
+ resulttype=self.lowleveltype)
+ else:
+ newopname = 'getsubstruct'
else:
newopname = 'getfield'
vlist = hop.inputargs(self, Void)
@@ -93,7 +101,18 @@
ARRAY = r_ptr.lowleveltype.TO
ITEM_TYPE = ARRAY.OF
if isinstance(ITEM_TYPE, ContainerType):
- newopname = 'getarraysubstruct'
+ if isinstance(hop.r_result, InteriorPtrRepr):
+ v_array, v_index = hop.inputargs(r_ptr, Signed)
+ INTERIOR_PTR_TYPE = r_ptr.lowleveltype._interior_ptr_type_with_index(ITEM_TYPE)
+ v_interior_ptr = hop.genop('malloc', [flowmodel.Constant(INTERIOR_PTR_TYPE, Void)],
+ resulttype = Ptr(INTERIOR_PTR_TYPE))
+ hop.genop('setfield',
+ [v_interior_ptr, flowmodel.Constant('ptr', Void), v_array])
+ hop.genop('setfield',
+ [v_interior_ptr, flowmodel.Constant('index', Void), v_index])
+ return v_interior_ptr
+ else:
+ newopname = 'getarraysubstruct'
else:
newopname = 'getarrayitem'
vlist = hop.inputargs(r_ptr, Signed)
@@ -154,15 +173,16 @@
class __extend__(annmodel.SomeLLADTMeth):
def rtyper_makerepr(self, rtyper):
- return LLADTMethRepr(self)
+ return LLADTMethRepr(self, rtyper)
def rtyper_makekey(self):
return self.__class__, self.ll_ptrtype, self.func
class LLADTMethRepr(Repr):
- def __init__(self, adtmeth):
+ def __init__(self, adtmeth, rtyper):
self.func = adtmeth.func
- self.lowleveltype = adtmeth.ll_ptrtype
+ self.ll_ptrtype = adtmeth.ll_ptrtype
+ self.lowleveltype = rtyper.getrepr(annmodel.lltype_to_annotation(adtmeth.ll_ptrtype)).lowleveltype
def rtype_simple_call(self, hop):
hop2 = hop.copy()
@@ -170,7 +190,7 @@
s_func = hop.rtyper.annotator.bookkeeper.immutablevalue(func)
v_ptr = hop2.args_v[0]
hop2.r_s_popfirstarg()
- hop2.v_s_insertfirstarg(v_ptr, annmodel.SomePtr(self.lowleveltype))
+ hop2.v_s_insertfirstarg(v_ptr, annmodel.lltype_to_annotation(self.ll_ptrtype))
hop2.v_s_insertfirstarg(flowmodel.Constant(func), s_func)
return hop2.dispatch()
@@ -181,4 +201,119 @@
return v
return NotImplemented
-
+
+class InteriorPtrRepr(Repr):
+ def __init__(self, ptrtype):
+ assert isinstance(ptrtype, InteriorPtr)
+ self.v_offsets = []
+ numitemoffsets = 0
+ for i, offset in enumerate(ptrtype.offsets):
+ if isinstance(offset, int):
+ numitemoffsets += 1
+ self.v_offsets.append(None)
+ else:
+ assert isinstance(offset, str)
+ self.v_offsets.append(flowmodel.Constant(offset, Void))
+ self.parentptrtype = Ptr(ptrtype.PARENTTYPE)
+ self.resulttype = Ptr(ptrtype.TO)
+ assert numitemoffsets <= 1
+ if numitemoffsets > 0:
+ self.lowleveltype = Ptr(self.parentptrtype._interior_ptr_type_with_index(self.resulttype.TO))
+ else:
+ self.lowleveltype = self.parentptrtype
+
+ def getinteriorfieldargs(self, hop, v_self):
+ vlist = []
+ if None in self.v_offsets:
+ INTERIOR_TYPE = v_self.concretetype.TO
+ nameiter = iter(INTERIOR_TYPE._names)
+ name = nameiter.next()
+ vlist.append(
+ hop.genop('getfield',
+ [v_self, flowmodel.Constant(name, Void)],
+ resulttype=INTERIOR_TYPE._flds[name]))
+ else:
+ vlist.append(v_self)
+ for v_offset in self.v_offsets:
+ if v_offset is None:
+ name = nameiter.next()
+ vlist.append(
+ hop.genop('getfield',
+ [v_self, flowmodel.Constant(name, Void)],
+ resulttype=INTERIOR_TYPE._flds[name]))
+ else:
+ vlist.append(v_offset)
+ if None in self.v_offsets:
+ try:
+ nameiter.next()
+ except StopIteration:
+ pass
+ else:
+ assert False
+ return vlist
+
+ def rtype_len(self, hop):
+ v_self, = hop.inputargs(self)
+ vlist = self.getinteriorfieldargs(hop, v_self)
+ return hop.genop('getinteriorarraysize', vlist,
+ resulttype=Signed)
+
+ def rtype_getattr(self, hop):
+ attr = hop.args_s[1].const
+ if isinstance(hop.s_result, annmodel.SomeLLADTMeth):
+ return hop.inputarg(hop.r_result, arg=0)
+ FIELD_TYPE = getattr(self.resulttype.TO, attr)
+ if isinstance(FIELD_TYPE, ContainerType):
+ return hop.genop('same_as', [hop.inputarg(self, 0)],
+ resulttype=self.lowleveltype)
+ else:
+ v_self, v_attr = hop.inputargs(self, Void)
+ vlist = self.getinteriorfieldargs(hop, v_self) + [v_attr]
+ return hop.genop('getinteriorfield', vlist,
+ resulttype=hop.r_result.lowleveltype)
+
+ def rtype_setattr(self, hop):
+ attr = hop.args_s[1].const
+ FIELD_TYPE = getattr(self.resulttype.TO, attr)
+ assert not isinstance(FIELD_TYPE, ContainerType)
+ v_self, v_fieldname, v_value = hop.inputargs(self, Void, hop.args_r[2])
+ vlist = self.getinteriorfieldargs(hop, v_self) + [v_fieldname, v_value]
+ return hop.genop('setinteriorfield', vlist)
+
+
+
+
+class __extend__(pairtype(InteriorPtrRepr, IntegerRepr)):
+ def rtype_getitem((r_ptr, r_item), hop):
+ ARRAY = r_ptr.resulttype.TO
+ ITEM_TYPE = ARRAY.OF
+ if isinstance(ITEM_TYPE, ContainerType):
+ v_array, v_index = hop.inputargs(r_ptr, Signed)
+ INTERIOR_PTR_TYPE = r_ptr.lowleveltype._interior_ptr_type_with_index(ITEM_TYPE)
+ v_interior_ptr = hop.genop('malloc', [flowmodel.Constant(INTERIOR_PTR_TYPE, Void)],
+ resulttype = Ptr(INTERIOR_PTR_TYPE))
+ hop.genop('setfield',
+ [v_interior_ptr, flowmodel.Constant('ptr', Void), v_array])
+ hop.genop('setfield',
+ [v_interior_ptr, flowmodel.Constant('index', Void), v_index])
+ return v_interior_ptr
+ else:
+ v_self, v_index = hop.inputargs(r_ptr, Signed)
+ vlist = r_ptr.getinteriorfieldargs(hop, v_self) + [v_index]
+ return hop.genop('getinteriorfield', vlist,
+ resulttype=ITEM_TYPE)
+
+ def rtype_setitem((r_ptr, r_index), hop):
+ ARRAY = r_ptr.resulttype.TO
+ ITEM_TYPE = ARRAY.OF
+ assert not isinstance(ITEM_TYPE, ContainerType)
+ v_self, v_index, v_value = hop.inputargs(r_ptr, Signed, hop.args_r[2])
+ vlist = r_ptr.getinteriorfieldargs(hop, v_self) + [v_index, v_value]
+ hop.genop('setinteriorfield', vlist)
+
+class __extend__(pairtype(InteriorPtrRepr, LLADTMethRepr)):
+
+ def convert_from_to((r_from, r_to), v, llops):
+ if r_from.lowleveltype == r_to.lowleveltype:
+ return v
+ return NotImplemented
Modified: pypy/branch/kill-keepalives/pypy/rpython/test/test_rdict.py
==============================================================================
--- pypy/branch/kill-keepalives/pypy/rpython/test/test_rdict.py (original)
+++ pypy/branch/kill-keepalives/pypy/rpython/test/test_rdict.py Wed Sep 13 11:50:52 2006
@@ -548,7 +548,7 @@
res = self.interpret(func2, [ord(x), ord(y)])
for i in range(len(res.entries)):
- assert not (res.entries[i].everused() and not res.entries[i].valid())
+ assert not (res.entry_everused(i) and not res.entry_valid(i))
def func3(c0, c1, c2, c3, c4, c5, c6, c7):
d = {}
@@ -568,7 +568,7 @@
for i in range(rdict.DICT_INITSIZE)])
count_frees = 0
for i in range(len(res.entries)):
- if not res.entries[i].everused():
+ if not res.entry_everused(i):
count_frees += 1
assert count_frees >= 3
@@ -659,8 +659,8 @@
res = self.interpret(f, [])
assert res.item0 == True
DICT = lltype.typeOf(res.item1).TO
- assert not hasattr(DICT.entries.TO.OF, 'f_everused')# non-None string keys
- assert not hasattr(DICT.entries.TO.OF, 'f_valid') # strings have a dummy
+ assert not DICT.entry_has_f_everused# non-None string keys
+ assert not DICT.entry_has_f_valid # strings have a dummy
def test_opt_nullvaluemarker(self):
def f(n):
@@ -670,8 +670,8 @@
res = self.interpret(f, [-5])
assert res.item0 == 4
DICT = lltype.typeOf(res.item1).TO
- assert not hasattr(DICT.entries.TO.OF, 'f_everused')# non-None str values
- assert not hasattr(DICT.entries.TO.OF, 'f_valid') # strs have a dummy
+ assert not DICT.entry_has_f_everused# non-None string keys
+ assert not DICT.entry_has_f_valid # strings have a dummy
def test_opt_nonullmarker(self):
class A:
@@ -687,8 +687,8 @@
res = self.interpret(f, [-5])
assert res.item0 == -5441
DICT = lltype.typeOf(res.item1).TO
- assert hasattr(DICT.entries.TO.OF, 'f_everused') # can-be-None A instances
- assert not hasattr(DICT.entries.TO.OF, 'f_valid')# with a dummy A instance
+ assert DICT.entry_has_f_everused # can-be-None A instances
+ assert not DICT.entry_has_f_valid# with a dummy A instance
res = self.interpret(f, [6])
assert res.item0 == -5441
@@ -703,8 +703,8 @@
assert res.item0 == 1
assert res.item1 == 24
DICT = lltype.typeOf(res.item2).TO
- assert hasattr(DICT.entries.TO.OF, 'f_everused') # all ints can be zero
- assert not hasattr(DICT.entries.TO.OF, 'f_valid')# nonneg int: dummy -1
+ assert DICT.entry_has_f_everused # all ints can be zero
+ assert not DICT.entry_has_f_valid# nonneg int: dummy -1
def test_opt_no_dummy(self):
def f(n):
@@ -716,8 +716,8 @@
assert res.item0 == 1
assert res.item1 == -24
DICT = lltype.typeOf(res.item2).TO
- assert hasattr(DICT.entries.TO.OF, 'f_everused') # all ints can be zero
- assert hasattr(DICT.entries.TO.OF, 'f_valid') # no dummy available
+ assert DICT.entry_has_f_everused # all ints can be zero
+ assert DICT.entry_has_f_valid # no dummy available
def test_opt_multiple_identical_dicts(self):
def f(n):
@@ -748,7 +748,3 @@
return dic[i]
res = self.interpret(func, [5])
assert res.ll_get(5) is res
-
-
-
-
Modified: pypy/branch/kill-keepalives/pypy/rpython/test/test_rptr.py
==============================================================================
--- pypy/branch/kill-keepalives/pypy/rpython/test/test_rptr.py (original)
+++ pypy/branch/kill-keepalives/pypy/rpython/test/test_rptr.py Wed Sep 13 11:50:52 2006
@@ -204,3 +204,63 @@
fptr(*(x,y))
py.test.raises(TypeError, "interpret(wrong, [1, 2])")
+
+
+def test_interior_ptr():
+ S = Struct("S", ('x', Signed))
+ T = GcStruct("T", ('s', S))
+ def f():
+ t = malloc(T)
+ t.s.x = 1
+ return t.s.x
+ res = interpret(f, [])
+ assert res == 1
+
+def test_interior_ptr_with_index():
+ S = Struct("S", ('x', Signed))
+ T = GcArray(S)
+ def f():
+ t = malloc(T, 1)
+ t[0].x = 1
+ return t[0].x
+ res = interpret(f, [])
+ assert res == 1
+
+def test_interior_ptr_with_field_and_index():
+ S = Struct("S", ('x', Signed))
+ T = GcStruct("T", ('items', Array(S)))
+ def f():
+ t = malloc(T, 1)
+ t.items[0].x = 1
+ return t.items[0].x
+ res = interpret(f, [])
+ assert res == 1
+
+def test_interior_ptr_with_index_and_field():
+ S = Struct("S", ('x', Signed))
+ T = Struct("T", ('s', S))
+ U = GcArray(T)
+ def f():
+ u = malloc(U, 1)
+ u[0].s.x = 1
+ return u[0].s.x
+ res = interpret(f, [])
+ assert res == 1
+
+def test_interior_ptr_len():
+ S = Struct("S", ('x', Signed))
+ T = GcStruct("T", ('items', Array(S)))
+ def f():
+ t = malloc(T, 1)
+ return len(t.items)
+ res = interpret(f, [])
+ assert res == 1
+
+def test_interior_ptr_with_setitem():
+ T = GcStruct("T", ('s', Array(Signed)))
+ def f():
+ t = malloc(T, 1)
+ t.s[0] = 1
+ return t.s[0]
+ res = interpret(f, [])
+ assert res == 1
Modified: pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py (original)
+++ pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py Wed Sep 13 11:50:52 2006
@@ -416,9 +416,9 @@
return result
def generic_set(self, op, targetexpr):
- newvalue = self.expr(op.args[2], special_case_void=False)
+ newvalue = self.expr(op.args[-1], special_case_void=False)
result = ['%s = %s;' % (targetexpr, newvalue)]
- T = self.lltypemap(op.args[2])
+ T = self.lltypemap(op.args[-1])
result = '\n'.join(result)
if T is Void:
result = '/* %s */' % result
@@ -432,7 +432,7 @@
op.args[1].value)
return self.generic_get(op, expr)
- def OP_SETFIELD(self, op):
+ def OP_BARE_SETFIELD(self, op):
assert isinstance(op.args[1], Constant)
STRUCT = self.lltypemap(op.args[0]).TO
structdef = self.db.gettypedefnode(STRUCT)
@@ -440,7 +440,7 @@
op.args[1].value)
return self.generic_set(op, expr)
- OP_BARE_SETFIELD = OP_SETFIELD
+ #OP_SETFIELD = OP_BARE_SETFIELD
def OP_GETSUBSTRUCT(self, op):
RESULT = self.lltypemap(op.result).TO
@@ -466,7 +466,7 @@
return self.generic_get(op, '%s[%s]' % (items,
self.expr(op.args[1])))
- def OP_SETARRAYITEM(self, op):
+ def OP_BARE_SETARRAYITEM(self, op):
ARRAY = self.lltypemap(op.args[0]).TO
items = self.expr(op.args[0])
if not isinstance(ARRAY, FixedSizeArray):
@@ -474,6 +474,42 @@
return self.generic_set(op, '%s[%s]' % (items,
self.expr(op.args[1])))
+ def interior_expr(self, args, rettype=False):
+ TYPE = args[0].concretetype.TO
+ expr = '(*(' + self.expr(args[0]) + '))'
+ for arg in args[1:]:
+ defnode = self.db.gettypedefnode(TYPE)
+ if arg.concretetype is Void:
+ fieldname = arg.value
+ expr = defnode.access_expr(expr, fieldname)
+ TYPE = getattr(TYPE, fieldname)
+ else:
+ if not isinstance(TYPE, FixedSizeArray):
+ expr = '(%s).items[%s]'%(expr, self.expr(arg))
+ else:
+ expr = '(%s)[%s]'%(expr, self.expr(arg))
+ TYPE = TYPE.OF
+ if rettype:
+ return expr, TYPE
+ else:
+ return expr
+
+ def OP_GETINTERIORFIELD(self, op):
+ return self.generic_get(op, self.interior_expr(op.args))
+
+ def OP_BARE_SETINTERIORFIELD(self, op):
+ return self.generic_set(op, self.interior_expr(op.args[:-1]))
+
+ def OP_GETINTERIORARRAYSIZE(self, op):
+ expr, ARRAY = self.interior_expr(op.args, True)
+ if isinstance(ARRAY, FixedSizeArray):
+ return '%s = %d;'%(self.expr(op.result), ARRAY.length)
+ else:
+ assert isinstance(ARRAY, Array)
+ return '%s = %s.length;'%(self.expr(op.result), expr)
+
+ #OP_SETINTERIORFIELD = OP_BARE_SETINTERIORFIELD
+
def OP_GETARRAYSUBSTRUCT(self, op):
ARRAY = self.lltypemap(op.args[0]).TO
items = self.expr(op.args[0])
Modified: pypy/branch/kill-keepalives/pypy/translator/c/src/support.h
==============================================================================
--- pypy/branch/kill-keepalives/pypy/translator/c/src/support.h (original)
+++ pypy/branch/kill-keepalives/pypy/translator/c/src/support.h Wed Sep 13 11:50:52 2006
@@ -18,12 +18,12 @@
#define FAIL_ZER(msg) FAIL_EXCEPTION(PyExc_ZeroDivisionError, msg)
#define CFAIL() RPyConvertExceptionFromCPython()
-#define PyString_FromLLCharArrayAndSize(itemsarray, size) \
- PyString_FromStringAndSize(itemsarray->items, size)
+#define PyString_FromRPyString(rpystr) \
+ PyString_FromStringAndSize(RPyString_AsString(rpystr), RPyString_Size(rpystr))
-#define PyString_ToLLCharArray(s, itemsarray) \
- memcpy(itemsarray->items, PyString_AS_STRING(s), \
- itemsarray->length)
+#define PyString_ToRPyString(s, rpystr) \
+ memcpy(RPyString_AsString(rpystr), PyString_AS_STRING(s), \
+ RPyString_Size(rpystr))
#ifndef PYPY_STANDALONE
More information about the Pypy-commit
mailing list