[pypy-svn] r47205 - in pypy/branch/kill-keepalives-again/pypy/rpython: lltypesystem rctypes rctypes/test

arigo at codespeak.net arigo at codespeak.net
Fri Oct 5 22:13:12 CEST 2007


Author: arigo
Date: Fri Oct  5 22:13:09 2007
New Revision: 47205

Modified:
   pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/llmemory.py
   pypy/branch/kill-keepalives-again/pypy/rpython/rctypes/rarray.py
   pypy/branch/kill-keepalives-again/pypy/rpython/rctypes/rchar_p.py
   pypy/branch/kill-keepalives-again/pypy/rpython/rctypes/rmodel.py
   pypy/branch/kill-keepalives-again/pypy/rpython/rctypes/test/test_rfunc.py
Log:
Some progress on rctypes.  Based on a function unsafe_getfield(ptr, name),
which does that a plain getattr(ptr, name) used to do before the introduction
of interior pointer objects.  In other words, it's grossly unsafe unless we
put enough keepalives by hand around it, and has no chance to be safe on a
moving GC.  Good enough for rctypes.


Modified: pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/llmemory.py	Fri Oct  5 22:13:09 2007
@@ -297,6 +297,7 @@
 def offsetof(TYPE, fldname):
     assert fldname in TYPE._flds
     return FieldOffset(TYPE, fldname)
+offsetof._annspecialcase_ = 'specialize:memo'
 
 def itemoffsetof(TYPE, n=0):
     return ArrayItemsOffset(TYPE) + ItemOffset(TYPE.OF) * n

Modified: pypy/branch/kill-keepalives-again/pypy/rpython/rctypes/rarray.py
==============================================================================
--- pypy/branch/kill-keepalives-again/pypy/rpython/rctypes/rarray.py	(original)
+++ pypy/branch/kill-keepalives-again/pypy/rpython/rctypes/rarray.py	Fri Oct  5 22:13:09 2007
@@ -7,11 +7,13 @@
 from pypy.annotation.pairtype import pairtype
 from pypy.rpython.rctypes.rmodel import CTypesRefRepr, CTypesValueRepr
 from pypy.rpython.rctypes.rmodel import genreccopy_arrayitem, reccopy, C_ZERO
+from pypy.rpython.rctypes.rmodel import unsafe_getfield
 from pypy.rpython.rctypes.rprimitive import PrimitiveRepr
 from pypy.rpython.rctypes.rpointer import PointerRepr
 from pypy.rpython.rctypes.aarray import VarSizedArrayType
 from pypy.annotation.model import SomeCTypesObject
 from pypy.objspace.flow.model import Constant
+from pypy.rlib.objectmodel import keepalive_until_here
 
 ArrayType = type(ARRAY(c_int, 10))
 
@@ -171,12 +173,13 @@
 
 def ll_chararrayvalue(box):
     from pypy.rpython.rctypes import rchar_p
-    p = box.c_data
+    p = unsafe_getfield(box, 'c_data')
     length = rchar_p.ll_strnlen(lltype.direct_arrayitems(p), len(p))
     newstr = lltype.malloc(string_repr.lowleveltype.TO, length)
     newstr.hash = 0
     for i in range(length):
         newstr.chars[i] = p[i]
+    keepalive_until_here(box)
     return newstr
 
 def ll_chararrayslice(box, slice):

Modified: pypy/branch/kill-keepalives-again/pypy/rpython/rctypes/rchar_p.py
==============================================================================
--- pypy/branch/kill-keepalives-again/pypy/rpython/rctypes/rchar_p.py	(original)
+++ pypy/branch/kill-keepalives-again/pypy/rpython/rctypes/rchar_p.py	Fri Oct  5 22:13:09 2007
@@ -3,6 +3,7 @@
 from pypy.rpython.rstr import AbstractStringRepr
 from pypy.rpython.lltypesystem.rstr import string_repr
 from pypy.rpython.rctypes.rmodel import CTypesValueRepr, C_ZERO
+from pypy.rpython.rctypes.rmodel import unsafe_getfield
 from pypy.rpython.rctypes.rarray import ArrayRepr
 from pypy.rpython.rctypes.rstringbuf import StringBufRepr
 from pypy.annotation.pairtype import pairtype
@@ -116,7 +117,7 @@
     return i
 
 def ll_str2charp(s):
-    return lltype.direct_arrayitems(s.chars)
+    return lltype.direct_arrayitems(unsafe_getfield(s, 'chars'))
 
 def ll_charp2str(p):
     if not p:

Modified: pypy/branch/kill-keepalives-again/pypy/rpython/rctypes/rmodel.py
==============================================================================
--- pypy/branch/kill-keepalives-again/pypy/rpython/rctypes/rmodel.py	(original)
+++ pypy/branch/kill-keepalives-again/pypy/rpython/rctypes/rmodel.py	Fri Oct  5 22:13:09 2007
@@ -93,21 +93,15 @@
             else:
                 # we must return a non-memory-owning box that keeps the
                 # memory-owning box alive
+                pdata = unsafe_getfield(p, 'c_data')
                 result = lltype.malloc(self.lowleveltype.TO, zero=True)
-                result.c_data = p.c_data    # initialize c_data pointer
+                result.c_data = pdata    # initialize c_data pointer
                 result.c_data_owner_keepalive = p
             self.const_cache[key] = result, keepalive
             return result
 
     def get_c_data(self, llops, v_box):
-        if self.ownsmemory:
-            inputargs = [v_box, inputconst(lltype.Void, "c_data")]
-            return llops.genop('getsubstruct', inputargs,
-                        lltype.Ptr(self.c_data_type) )
-        else:
-            inputargs = [v_box, inputconst(lltype.Void, "c_data")]
-            return llops.genop('getfield', inputargs,
-                        lltype.Ptr(self.c_data_type) )
+        return gen_unsafe_getfield(llops, v_box, 'c_data')
 
     def get_c_data_owner(self, llops, v_box):
         if self.ownsmemory:
@@ -162,19 +156,10 @@
         return self.allocate_instance_ref(llops, v_c_data)
 
     def getkeepalive(self, llops, v_box):
-        try:
-            TYPE = self.lowleveltype.TO.keepalive
-        except AttributeError:
-            return None
+        if hasattr(self.lowleveltype.TO, 'keepalive'):
+            return gen_unsafe_getfield(llops, v_box, 'keepalive')
         else:
-            if isinstance(TYPE, lltype.ContainerType):
-                TYPE = lltype.Ptr(TYPE)
-                opname = 'getsubstruct'
-            else:
-                opname = 'getfield'
-            c_name = inputconst(lltype.Void, 'keepalive')
-            return llops.genop(opname, [v_box, c_name],
-                               resulttype = TYPE)
+            return None
 
 
 class __extend__(pairtype(CTypesRepr, CTypesRepr)):
@@ -263,6 +248,39 @@
 
 C_ZERO = inputconst(lltype.Signed, 0)
 
+def unsafe_getfield(ptr, name):
+    """Equivalent of getattr(ptr, name), but if the 'name' belongs to an
+    inlined substructure of a GC pointer, it returns a raw pointer to it.
+    This is dangerous!  You *have* to keep the 'ptr' alive as long as you
+    use the result - put a call to keepalive_until_here()."""
+    STRUCT = lltype.typeOf(ptr).TO
+    FIELD = getattr(STRUCT, name)
+    if isinstance(FIELD, lltype.ContainerType):
+        addr = llmemory.cast_ptr_to_adr(ptr)
+        addr += llmemory.offsetof(STRUCT, name)
+        return llmemory.cast_adr_to_ptr(addr, lltype.Ptr(FIELD))
+    else:
+        return getattr(ptr, name)
+unsafe_getfield._annspecialcase_ = 'specialize:ll_and_arg(1)'
+
+def gen_unsafe_getfield(llops, v_ptr, name):
+    """Generate lloperations equivalent to 'unsafe_getfield(ptr, name)'."""
+    STRUCT = v_ptr.concretetype.TO
+    assert isinstance(STRUCT, lltype.Struct)
+    FIELD = getattr(STRUCT, name)
+    if isinstance(FIELD, lltype.ContainerType):
+        v_addr = llops.genop('cast_ptr_to_adr', [v_ptr],
+                             resulttype = llmemory.Address)
+        c_ofs = inputconst(lltype.Signed, llmemory.offsetof(STRUCT, name))
+        v_addr = llops.genop('adr_add', [v_addr, c_ofs],
+                             resulttype = llmemory.Address)
+        return llops.genop('cast_adr_to_ptr', [v_addr],
+                           resulttype = lltype.Ptr(FIELD))
+    else:
+        c_name = inputconst(lltype.Void, name)
+        return llops.genop('getfield', [v_ptr, c_name],
+                           resulttype = FIELD)
+
 def reccopy(source, dest):
     # copy recursively a structure or array onto another.
     T = lltype.typeOf(source).TO

Modified: pypy/branch/kill-keepalives-again/pypy/rpython/rctypes/test/test_rfunc.py
==============================================================================
--- pypy/branch/kill-keepalives-again/pypy/rpython/rctypes/test/test_rfunc.py	(original)
+++ pypy/branch/kill-keepalives-again/pypy/rpython/rctypes/test/test_rfunc.py	Fri Oct  5 22:13:09 2007
@@ -5,6 +5,7 @@
 import py
 import sys
 import pypy.rpython.rctypes.implementation
+from pypy.rpython.rctypes.rmodel import unsafe_getfield
 from pypy.annotation import model as annmodel
 from pypy.annotation.annrpython import RPythonAnnotator
 from pypy.translator.translator import TranslationContext, graphof
@@ -109,7 +110,7 @@
     def str2subarray(string):
         llstring = string_repr.convert_const(string)
         keepalive.append(llstring)
-        return lltype.direct_arrayitems(llstring.chars)
+        return lltype.direct_arrayitems(unsafe_getfield(llstring, 'chars'))
     assert ll_atoi(str2subarray("")) == 0
     assert ll_atoi(str2subarray("42z7")) == 42
     assert ll_atoi(str2subarray("blah")) == 0



More information about the Pypy-commit mailing list