[pypy-svn] r47109 - in pypy/branch/kill-keepalives-again/pypy: annotation rpython rpython/lltypesystem rpython/test
cfbolz at codespeak.net
cfbolz at codespeak.net
Wed Oct 3 00:51:41 CEST 2007
Author: cfbolz
Date: Wed Oct 3 00:51:40 2007
New Revision: 47109
Modified:
pypy/branch/kill-keepalives-again/pypy/annotation/bookkeeper.py
pypy/branch/kill-keepalives-again/pypy/annotation/builtin.py
pypy/branch/kill-keepalives-again/pypy/annotation/model.py
pypy/branch/kill-keepalives-again/pypy/annotation/unaryop.py
pypy/branch/kill-keepalives-again/pypy/rpython/llinterp.py
pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/lloperation.py
pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/lltype.py
pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/opimpl.py
pypy/branch/kill-keepalives-again/pypy/rpython/rptr.py
pypy/branch/kill-keepalives-again/pypy/rpython/test/test_rptr.py
Log:
first step in reviving the kill-keepalive branch: make the new way of rtyping
the access of interior pointers work again. rptr tests pass.
Modified: pypy/branch/kill-keepalives-again/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/branch/kill-keepalives-again/pypy/annotation/bookkeeper.py (original)
+++ pypy/branch/kill-keepalives-again/pypy/annotation/bookkeeper.py Wed Oct 3 00:51:40 2007
@@ -11,7 +11,7 @@
SomeInteger, SomeExternalObject, SomeOOInstance, TLS, SomeAddress, \
SomeUnicodeCodePoint, SomeOOStaticMeth, s_None, s_ImpossibleValue, \
SomeLLADTMeth, SomeBool, SomeTuple, SomeOOClass, SomeImpossibleValue, \
- SomeList, SomeObject, HarmlesslyBlocked, SomeWeakRef
+ SomeList, SomeObject, HarmlesslyBlocked, SomeWeakRef, 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
@@ -239,7 +239,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-again/pypy/annotation/builtin.py
==============================================================================
--- pypy/branch/kill-keepalives-again/pypy/annotation/builtin.py (original)
+++ pypy/branch/kill-keepalives-again/pypy/annotation/builtin.py Wed Oct 3 00:51:40 2007
@@ -628,7 +628,6 @@
# memory address
from pypy.rpython.memory import lladdress
-from pypy.rpython.lltypesystem import llmemory
def raw_malloc(s_size):
assert isinstance(s_size, SomeInteger) #XXX add noneg...?
@@ -669,7 +668,6 @@
#_________________________________
# offsetof/sizeof
-from pypy.rpython.lltypesystem import llmemory
def offsetof(TYPE, fldname):
return SomeInteger()
Modified: pypy/branch/kill-keepalives-again/pypy/annotation/model.py
==============================================================================
--- pypy/branch/kill-keepalives-again/pypy/annotation/model.py (original)
+++ pypy/branch/kill-keepalives-again/pypy/annotation/model.py Wed Oct 3 00:51:40 2007
@@ -551,6 +551,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):
@@ -597,6 +602,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:
@@ -630,6 +642,8 @@
return SomeOOClass(ootype.ROOT)
elif isinstance(T, ExternalType):
return SomeExternalInstance(T._class_)
+ elif isinstance(T, lltype.InteriorPtr):
+ return SomeInteriorPtr(T)
else:
return SomePtr(T)
else:
@@ -642,13 +656,19 @@
return s_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-again/pypy/annotation/unaryop.py
==============================================================================
--- pypy/branch/kill-keepalives-again/pypy/annotation/unaryop.py (original)
+++ pypy/branch/kill-keepalives-again/pypy/annotation/unaryop.py Wed Oct 3 00:51:40 2007
@@ -691,7 +691,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-again/pypy/rpython/llinterp.py
==============================================================================
--- pypy/branch/kill-keepalives-again/pypy/rpython/llinterp.py (original)
+++ pypy/branch/kill-keepalives-again/pypy/rpython/llinterp.py Wed Oct 3 00:51:40 2007
@@ -558,6 +558,31 @@
result = self.op_direct_call(write_barrier, *args)
op_bare_setfield = op_setfield
+ def op_getinteriorfield(self, 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_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
+ op_bare_setinteriorfield = op_setinteriorfield
+
def op_getarrayitem(self, array, index):
return array[index]
Modified: pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/lloperation.py (original)
+++ pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/lloperation.py Wed Oct 3 00:51:40 2007
@@ -320,6 +320,9 @@
'getarrayitem': LLOp(sideeffects=False, canrun=True),
'getarraysize': LLOp(canfold=True),
'getsubstruct': LLOp(canfold=True),
+ 'getinteriorfield': LLOp(sideeffects=False, canrun=True),
+ 'getinteriorarraysize': LLOp(canfold=True),
+ 'setinteriorfield': LLOp(),
'getarraysubstruct': LLOp(canfold=True),
'setfield': LLOp(),
'bare_setfield': LLOp(),
Modified: pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/lltype.py (original)
+++ pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/lltype.py Wed Oct 3 00:51:40 2007
@@ -631,6 +631,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
# ____________________________________________________________
@@ -667,6 +695,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,
@@ -850,13 +884,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:
@@ -903,26 +930,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
@@ -930,19 +945,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:
@@ -997,7 +1001,7 @@
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]
@@ -1013,20 +1017,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:
@@ -1050,7 +1040,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):
@@ -1124,6 +1114,34 @@
return callb(*args)
raise TypeError("%r instance is not a function" % (self._T,))
+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 _cast_to(self, PTRTYPE):
CURTYPE = self._TYPE
down_or_up = castable(PTRTYPE, CURTYPE)
@@ -1188,8 +1206,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):
@@ -1261,7 +1338,8 @@
if parent is None:
break
T = typeOf(parent)
- if not isinstance(T, Struct) or T._first_struct()[0] != index:
+ if (not isinstance(T, Struct) or T._first_struct()[0] != index
+ or isinstance(T, FixedSizeArray)):
break
container = parent
return container
Modified: pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/opimpl.py
==============================================================================
--- pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/opimpl.py (original)
+++ pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/opimpl.py Wed Oct 3 00:51:40 2007
@@ -120,6 +120,31 @@
# the diff between op_getarrayitem and op_getarraysubstruct
# is the same as between op_getfield and op_getsubstruct
+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_getinteriorfield(obj, *offsets):
+ checkptr(obj)
+ ob = obj
+ T = lltype.typeOf(obj).TO
+ for o in offsets:
+ if not T._hints.get('immutable'):
+ raise TypeError("cannot fold getinteriorfield on mutable struct")
+ if isinstance(o, str):
+ ob = getattr(ob, o)
+ T = getattr(T, o)
+ else:
+ raise TypeError("cannot fold getfield on mutable struct")
+ assert not isinstance(ob, lltype._interior_ptr)
+ return ob
+
def op_getarraysize(array):
checkptr(array)
return len(array)
Modified: pypy/branch/kill-keepalives-again/pypy/rpython/rptr.py
==============================================================================
--- pypy/branch/kill-keepalives-again/pypy/rpython/rptr.py (original)
+++ pypy/branch/kill-keepalives-again/pypy/rpython/rptr.py Wed Oct 3 00:51:40 2007
@@ -19,6 +19,10 @@
## else:
return self.__class__, self.ll_ptrtype
+class __extend__(annmodel.SomeInteriorPtr):
+ def rtyper_makerepr(self, rtyper):
+ return InteriorPtrRepr(self.ll_ptrtype)
+
class PtrRepr(Repr):
@@ -37,7 +41,14 @@
return hop.inputarg(hop.r_result, arg=0)
FIELD_TYPE = getattr(self.lowleveltype.TO, attr)
if isinstance(FIELD_TYPE, lltype.ContainerType):
- newopname = 'getsubstruct'
+ if (attr, FIELD_TYPE) == self.lowleveltype.TO._first_struct():
+ return hop.genop('cast_pointer', [hop.inputarg(self, 0)],
+ resulttype=hop.r_result.lowleveltype)
+ elif 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, lltype.Void)
@@ -98,7 +109,21 @@
ARRAY = r_ptr.lowleveltype.TO
ITEM_TYPE = ARRAY.OF
if isinstance(ITEM_TYPE, lltype.ContainerType):
- newopname = 'getarraysubstruct'
+ if isinstance(hop.r_result, InteriorPtrRepr):
+ v_array, v_index = hop.inputargs(r_ptr, lltype.Signed)
+ INTERIOR_PTR_TYPE = r_ptr.lowleveltype._interior_ptr_type_with_index(ITEM_TYPE)
+ cflags = hop.inputconst(lltype.Void, {'flavor': 'gc'})
+ args = [flowmodel.Constant(INTERIOR_PTR_TYPE, lltype.Void),
+ cflags]
+ v_interior_ptr = hop.genop('malloc', args,
+ resulttype=lltype.Ptr(INTERIOR_PTR_TYPE))
+ hop.genop('setfield',
+ [v_interior_ptr, flowmodel.Constant('ptr', lltype.Void), v_array])
+ hop.genop('setfield',
+ [v_interior_ptr, flowmodel.Constant('index', lltype.Void), v_index])
+ return v_interior_ptr
+ else:
+ newopname = 'getarraysubstruct'
else:
newopname = 'getarrayitem'
vlist = hop.inputargs(r_ptr, lltype.Signed)
@@ -159,23 +184,26 @@
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()
func = self.func
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()
@@ -186,4 +214,121 @@
return v
return NotImplemented
-
+class InteriorPtrRepr(Repr):
+ def __init__(self, ptrtype):
+ assert isinstance(ptrtype, lltype.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, lltype.Void))
+ self.parentptrtype = lltype.Ptr(ptrtype.PARENTTYPE)
+ self.resulttype = lltype.Ptr(ptrtype.TO)
+ assert numitemoffsets <= 1
+ if numitemoffsets > 0:
+ self.lowleveltype = lltype.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, lltype.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, lltype.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=lltype.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, lltype.ContainerType):
+ return hop.genop('same_as', [hop.inputarg(self, 0)],
+ resulttype=self.lowleveltype)
+ else:
+ v_self, v_attr = hop.inputargs(self, lltype.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, lltype.ContainerType)
+ v_self, v_fieldname, v_value = hop.inputargs(self, lltype.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, lltype.ContainerType):
+ v_array, v_index = hop.inputargs(r_ptr, lltype.Signed)
+ INTERIOR_PTR_TYPE = r_ptr.lowleveltype._interior_ptr_type_with_index(ITEM_TYPE)
+ cflags = hop.inputconst(lltype.Void, {'flavor': 'gc'})
+ args = [flowmodel.Constant(INTERIOR_PTR_TYPE, lltype.Void), cflags]
+ v_interior_ptr = hop.genop('malloc', args,
+ resulttype=lltype.Ptr(INTERIOR_PTR_TYPE))
+ hop.genop('setfield',
+ [v_interior_ptr, flowmodel.Constant('ptr', lltype.Void), v_array])
+ hop.genop('setfield',
+ [v_interior_ptr, flowmodel.Constant('index', lltype.Void), v_index])
+ return v_interior_ptr
+ else:
+ v_self, v_index = hop.inputargs(r_ptr, lltype.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, lltype.ContainerType)
+ v_self, v_index, v_value = hop.inputargs(r_ptr, lltype.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-again/pypy/rpython/test/test_rptr.py
==============================================================================
--- pypy/branch/kill-keepalives-again/pypy/rpython/test/test_rptr.py (original)
+++ pypy/branch/kill-keepalives-again/pypy/rpython/test/test_rptr.py Wed Oct 3 00:51:40 2007
@@ -234,3 +234,82 @@
res = interpret(f, [])
assert res.chars[0] == '0'
assert res.chars[1] == 'x'
+
+
+def test_first_subfield_access_is_cast_pointer():
+ B = GcStruct("B", ('x', Signed))
+ C = GcStruct("C", ('super', B), ('y', Signed))
+ def f():
+ c = malloc(C)
+ c.super.x = 1
+ c.y = 2
+ return c.super.x + c.y
+ s, t = ll_rtype(f, [])
+ from pypy.translator.translator import graphof
+ from pypy.objspace.flow.model import summary
+ graph = graphof(t, f)
+ graphsum = summary(graph)
+ assert 'getsubstruct' not in graphsum
+ assert 'cast_pointer' in graphsum
+
+
+
+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
+
More information about the Pypy-commit
mailing list