[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