[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