[pypy-svn] r77572 - in pypy/branch/32ptr-on-64bit/pypy: annotation config rpython rpython/lltypesystem rpython/memory rpython/memory/gc rpython/memory/test rpython/test translator/c translator/c/src translator/c/test

arigo at codespeak.net arigo at codespeak.net
Mon Oct 4 15:30:25 CEST 2010


Author: arigo
Date: Mon Oct  4 15:30:22 2010
New Revision: 77572

Added:
   pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/rcompressed.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/test/test_rcompressed.py
Modified:
   pypy/branch/32ptr-on-64bit/pypy/annotation/model.py
   pypy/branch/32ptr-on-64bit/pypy/config/translationoption.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/llmemory.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/lloperation.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/opimpl.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/rclass.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/rffi.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/memory/gc/base.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/memory/gc/minimark.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/memory/gctypelayout.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/memory/gcwrapper.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/memory/test/test_gc.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/memory/test/test_gctypelayout.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/raddress.py
   pypy/branch/32ptr-on-64bit/pypy/rpython/rmodel.py
   pypy/branch/32ptr-on-64bit/pypy/translator/c/database.py
   pypy/branch/32ptr-on-64bit/pypy/translator/c/node.py
   pypy/branch/32ptr-on-64bit/pypy/translator/c/primitive.py
   pypy/branch/32ptr-on-64bit/pypy/translator/c/src/commondefs.h
   pypy/branch/32ptr-on-64bit/pypy/translator/c/test/test_lladdresses.py
   pypy/branch/32ptr-on-64bit/pypy/translator/c/test/test_newgc.py
Log:
In-progress.


Modified: pypy/branch/32ptr-on-64bit/pypy/annotation/model.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/annotation/model.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/annotation/model.py	Mon Oct  4 15:30:22 2010
@@ -518,6 +518,14 @@
     def can_be_none(self):
         return False
 
+# for compressed 32-bit "pointers" on 64-bit platforms
+
+class SomeHiddenGcRef32(SomeObject):
+    immutable = True
+
+    def can_be_none(self):
+        return False
+
 #____________________________________________________________
 # annotation of low-level types
 
@@ -582,6 +590,7 @@
     (SomeChar(), lltype.Char),
     (SomeUnicodeCodePoint(), lltype.UniChar),
     (SomeAddress(), llmemory.Address),
+    (SomeHiddenGcRef32(), llmemory.HiddenGcRef32),
 ]
 
 def annotation_to_lltype(s_val, info=None):

Modified: pypy/branch/32ptr-on-64bit/pypy/config/translationoption.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/config/translationoption.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/config/translationoption.py	Mon Oct  4 15:30:22 2010
@@ -193,6 +193,11 @@
                "When true, enable the use of tagged pointers. "
                "If false, use normal boxing",
                default=False),
+    BoolOption("compressptr", "Compress pointers; limits the program to 32GB",
+               default=False, cmdline="--compressptr",
+               requires=[("translation.type_system", "lltype"),
+                         ("translation.taggedpointers", False)]
+               + [("compressptr (64-bit only)", True)]*(not IS_64_BITS)),
 
     # options for ootype
     OptionDescription("ootype", "Object Oriented Typesystem options", [

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/llmemory.py	Mon Oct  4 15:30:22 2010
@@ -8,6 +8,7 @@
 from pypy.rlib.objectmodel import Symbolic
 from pypy.rpython.lltypesystem import lltype
 from pypy.tool.uid import uid
+from pypy.rlib.objectmodel import we_are_translated
 
 class AddressOffset(Symbolic):
 
@@ -562,6 +563,61 @@
 def array_item_type_match(T1, T2):
     return T1 == T2 or (T2 == GCREF and isinstance(T1, lltype.Ptr))
 
+# ____________________________________________________________
+
+class _hiddengcref32(object):
+    """A 'hidden' compressed 32-bit value that represents a
+    full, 64-bit GC pointer."""
+
+    def __init__(self, adr64):
+        self.adr64 = adr64
+
+    def __repr__(self):
+        return '<_hiddengcref32>'
+
+    def __str__(self):
+        return '<_hiddengcref32 %s>' % (self.adr64,)
+
+compressed_null_addr = _hiddengcref32(NULL)
+HiddenGcRef32 = lltype.Primitive("HiddenGcRef32", compressed_null_addr)
+_hiddengcref32._TYPE = HiddenGcRef32
+
+class OddValueMarker(AddressOffset):
+    """This is the value '1'.  Used as an odd-valued marker by the GC."""
+    def __repr__(self):
+        return '< OddValueMarker 1 >'
+    def ref(self, ptr):
+        raise AssertionError("should not try to directly get the address"
+                             " from a HiddenGcRef32")
+
+def has_odd_value_marker(addressofs):
+    if we_are_translated():
+        return bool(addressofs & 1)
+    return _has_odd_value_marker(addressofs)
+
+def _has_odd_value_marker(addressofs):
+    while isinstance(addressofs, CompositeOffset):
+        addressofs = addressofs.offsets[-1]
+    return isinstance(addressofs, OddValueMarker)
+
+def remove_odd_value_marker(addressofs):
+    if we_are_translated():
+        return addressofs - 1
+    return _remove_odd_value_marker(addressofs)
+
+def _remove_odd_value_marker(addressofs):
+    if isinstance(addressofs, CompositeOffset):
+        offsets = list(addressofs.offsets)
+        offsets[-1] = _remove_odd_value_marker(offsets[-1])
+        if offsets[-1] == 0:
+            del offsets[-1]
+            if len(offsets) == 1:
+                return offsets[0]
+        return CompositeOffset(*offsets)
+    assert isinstance(addressofs, OddValueMarker)
+    return 0
+
+# ____________________________________________________________
 
 class _fakeaccessor(object):
     def __init__(self, addr):
@@ -597,6 +653,9 @@
 class _char_fakeaccessor(_fakeaccessor):
     TYPE = lltype.Char
 
+class _hiddengcref32_fakeaccessor(_fakeaccessor):
+    TYPE = HiddenGcRef32
+
 class _address_fakeaccessor(_fakeaccessor):
     TYPE = Address
 
@@ -624,12 +683,14 @@
                           "char":      lltype.Char,
                           "address":   Address,
                           "float":     lltype.Float,
+                          "hiddengcref32": HiddenGcRef32,
                           }
 
 fakeaddress.signed = property(_signed_fakeaccessor)
 fakeaddress.float = property(_float_fakeaccessor)
 fakeaddress.char = property(_char_fakeaccessor)
 fakeaddress.address = property(_address_fakeaccessor)
+fakeaddress.hiddengcref32 = property(_hiddengcref32_fakeaccessor)
 fakeaddress._TYPE = Address
 
 # the obtained address will not keep the object alive. e.g. if the object is

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/lloperation.py	Mon Oct  4 15:30:22 2010
@@ -426,6 +426,9 @@
     'gc_gettypeptr_group':  LLOp(canfold=True),
     'get_member_index':     LLOp(canfold=True),
 
+    'hide_into_adr32':      LLOp(canrun=True),
+    'show_from_adr32':      LLOp(canrun=True),
+
     # __________ used by the JIT ________
 
     'jit_marker':           LLOp(),

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/opimpl.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/opimpl.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/opimpl.py	Mon Oct  4 15:30:22 2010
@@ -526,6 +526,18 @@
 def op_shrink_array(array, smallersize):
     return False
 
+def op_hide_into_adr32(adr):
+    if lltype.typeOf(adr) != llmemory.Address:
+        adr = llmemory.cast_ptr_to_adr(adr)
+    return llmemory._hiddengcref32(adr)
+
+def op_show_from_adr32(RESTYPE, adr32):
+    if RESTYPE == llmemory.Address:
+        return adr32.adr64
+    else:
+        return llmemory.cast_adr_to_ptr(adr32.adr64, RESTYPE)
+op_show_from_adr32.need_result_type = True
+
 # ____________________________________________________________
 
 def get_op_impl(opname):

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/rclass.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/rclass.py	Mon Oct  4 15:30:22 2010
@@ -4,6 +4,7 @@
 from pypy.objspace.flow.model import Constant
 from pypy.rpython.error import TyperError
 from pypy.rpython.rmodel import Repr, inputconst, warning, mangle
+from pypy.rpython.rmodel import externalvsinternalfield
 from pypy.rpython.rclass import AbstractClassRepr,\
                                 AbstractInstanceRepr,\
                                 MissingRTypeAttribute,\
@@ -326,7 +327,8 @@
         fields = {}
         allinstancefields = {}
         if self.classdef is None:
-            fields['__class__'] = 'typeptr', get_type_repr(self.rtyper)
+            r = get_type_repr(self.rtyper)
+            fields['__class__'] = 'typeptr', r, r
         else:
             # instance attributes
             if llfields is None:
@@ -337,8 +339,12 @@
                 if not attrdef.readonly:
                     r = self.rtyper.getrepr(attrdef.s_value)
                     mangled_name = 'inst_' + name
-                    fields[name] = mangled_name, r
-                    llfields.append((mangled_name, r.lowleveltype))
+                    if self.gcflavor == 'gc':
+                        r, internal_r = externalvsinternalfield(self.rtyper, r)
+                    else:
+                        internal_r = r
+                    fields[name] = mangled_name, r, internal_r
+                    llfields.append((mangled_name, internal_r.lowleveltype))
 
             self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef,
                                          self.gcflavor)
@@ -394,7 +400,7 @@
         return getinstancerepr(self.rtyper, None, self.gcflavor)
 
     def _get_field(self, attr):
-        return self.fields[attr]
+        return self.fields[attr][:2]
 
     def null_instance(self):
         return nullptr(self.object_type)
@@ -410,7 +416,7 @@
             # recursively build the parent part of the instance
             self.rbase.initialize_prebuilt_data(value, classdef, result.super)
             # then add instance attributes from this level
-            for name, (mangled_name, r) in self.fields.items():
+            for name, (mangled_name, _, r) in self.fields.items():
                 if r.lowleveltype is Void:
                     llattrvalue = None
                 else:
@@ -440,7 +446,7 @@
     def getfieldrepr(self, attr):
         """Return the repr used for the given attribute."""
         if attr in self.fields:
-            mangled_name, r = self.fields[attr]
+            mangled_name, r, internal_r = self.fields[attr]
             return r
         else:
             if self.classdef is None:
@@ -450,12 +456,13 @@
     def getfield(self, vinst, attr, llops, force_cast=False, flags={}):
         """Read the given attribute (or __class__ for the type) of 'vinst'."""
         if attr in self.fields:
-            mangled_name, r = self.fields[attr]
+            mangled_name, r, internal_r = self.fields[attr]
             cname = inputconst(Void, mangled_name)
             if force_cast:
                 vinst = llops.genop('cast_pointer', [vinst], resulttype=self)
             self.hook_access_field(vinst, cname, llops, flags)
-            return llops.genop('getfield', [vinst, cname], resulttype=r)
+            v = llops.genop('getfield', [vinst, cname], resulttype=internal_r)
+            return llops.convertvar(v, internal_r, r)
         else:
             if self.classdef is None:
                 raise MissingRTypeAttribute(attr)
@@ -466,7 +473,8 @@
                  flags={}):
         """Write the given attribute (or __class__ for the type) of 'vinst'."""
         if attr in self.fields:
-            mangled_name, r = self.fields[attr]
+            mangled_name, r, internal_r = self.fields[attr]
+            vvalue = llops.convertvar(vvalue, r, internal_r)
             cname = inputconst(Void, mangled_name)
             if force_cast:
                 vinst = llops.genop('cast_pointer', [vinst], resulttype=self)
@@ -499,7 +507,7 @@
             for fldname in flds:
                 if fldname == '__class__':
                     continue
-                mangled_name, r = self.allinstancefields[fldname]
+                mangled_name, r, internal_r = self.allinstancefields[fldname]
                 if r.lowleveltype is Void:
                     continue
                 value = self.classdef.classdesc.read_attribute(fldname, None)

Added: pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/rcompressed.py
==============================================================================
--- (empty file)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/rcompressed.py	Mon Oct  4 15:30:22 2010
@@ -0,0 +1,57 @@
+from pypy.tool.pairtype import pairtype
+from pypy.rlib.objectmodel import we_are_translated
+from pypy.config.translationoption import IS_64_BITS
+from pypy.rpython.rmodel import Repr, inputconst
+from pypy.rpython.lltypesystem import lltype, llmemory, rffi
+
+
+
+def get_compressed_gcref_repr(rtyper, baserepr):
+    try:
+        comprmgr = rtyper.compressed_gcref_manager
+    except AttributeError:
+        comprmgr = rtyper.compressed_gcref_manager = ComprGcRefManager(rtyper)
+    return comprmgr.get_compressed_gcref_repr(baserepr)
+
+
+class ComprGcRefManager(object):
+    def __init__(self, rtyper):
+        assert IS_64_BITS                # this is only for 64-bits
+        self.rtyper = rtyper
+        self.comprgcreprs = {}
+
+    def get_compressed_gcref_repr(self, baserepr):
+        try:
+            return self.comprgcreprs[baserepr]
+        except KeyError:
+            comprgcrepr = CompressedGcRefRepr(self, baserepr)
+            self.comprgcreprs[baserepr] = comprgcrepr
+            return comprgcrepr
+
+
+class CompressedGcRefRepr(Repr):
+    lowleveltype = llmemory.HiddenGcRef32
+
+    def __init__(self, mgr, baserepr):
+        self.mgr = mgr
+        self.baserepr = baserepr
+        self.BASETYPE = self.baserepr.lowleveltype
+
+    def convert_const(self, value):
+        ptr = self.baserepr.convert_const(value)
+        T = lltype.typeOf(ptr)
+        assert T == self.BASETYPE
+        return llmemory._hiddengcref32(llmemory.cast_ptr_to_adr(ptr))
+
+
+class __extend__(pairtype(Repr, CompressedGcRefRepr)):
+    def convert_from_to((r_from, r_to), v, llops):
+        assert r_from.lowleveltype.TO._gckind == 'gc'
+        return llops.genop('hide_into_adr32', [v],
+                           resulttype=llmemory.HiddenGcRef32)
+
+class __extend__(pairtype(CompressedGcRefRepr, Repr)):
+    def convert_from_to((r_from, r_to), v, llops):
+        assert r_to.lowleveltype.TO._gckind == 'gc'
+        return llops.genop('show_from_adr32', [v],
+                           resulttype=r_to.lowleveltype)

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/rffi.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/rffi.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/lltypesystem/rffi.py	Mon Oct  4 15:30:22 2010
@@ -805,6 +805,8 @@
         return 8
     if tp is lltype.SingleFloat:
         return 4
+    if tp is llmemory.HiddenGcRef32:
+        return 4
     assert isinstance(tp, lltype.Number)
     if tp is lltype.Signed:
         return ULONG._type.BITS/8

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/memory/gc/base.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/memory/gc/base.py	Mon Oct  4 15:30:22 2010
@@ -1,4 +1,5 @@
 from pypy.rpython.lltypesystem import lltype, llmemory, llarena
+from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rlib.debug import ll_assert
 from pypy.rpython.memory.gcheader import GCHeaderBuilder
 from pypy.rpython.memory.support import DEFAULT_CHUNK_SIZE
@@ -168,8 +169,10 @@
 
     def trace(self, obj, callback, arg):
         """Enumerate the locations inside the given obj that can contain
-        GC pointers.  For each such location, callback(pointer, arg) is
-        called, where 'pointer' is an address inside the object.
+        GC pointers.  For each such GC pointer, callback(object, arg) is
+        called, where 'object' is the address of the stored object.
+        'callback' can return a new address that replaces the old one in
+        'obj', or it can return None.
         Typically, 'callback' is a bound method and 'arg' can be None.
         """
         typeid = self.get_type_id(obj)
@@ -179,16 +182,16 @@
             item = obj + llmemory.gcarrayofptr_itemsoffset
             while length > 0:
                 if self.points_to_valid_gc_object(item):
-                    callback(item, arg)
+                    newaddr = callback(item.address[0], arg)
+                    if newaddr is not None:
+                        item.address[0] = newaddr
                 item += llmemory.gcarrayofptr_singleitemoffset
                 length -= 1
             return
         offsets = self.offsets_to_gc_pointers(typeid)
         i = 0
         while i < len(offsets):
-            item = obj + offsets[i]
-            if self.points_to_valid_gc_object(item):
-                callback(item, arg)
+            self._trace_see(obj, offsets[i], callback, arg)
             i += 1
         if self.has_gcptr_in_varsize(typeid):
             item = obj + self.varsize_offset_to_variable_part(typeid)
@@ -198,14 +201,35 @@
             while length > 0:
                 j = 0
                 while j < len(offsets):
-                    itemobj = item + offsets[j]
-                    if self.points_to_valid_gc_object(itemobj):
-                        callback(itemobj, arg)
+                    self._trace_see(item, offsets[j], callback, arg)
                     j += 1
                 item += itemlength
                 length -= 1
     trace._annspecialcase_ = 'specialize:arg(2)'
 
+    def _trace_see(self, obj, ofs, callback, arg):
+        if self.config.compressptr and llmemory.has_odd_value_marker(ofs):
+            # special handling of HiddenGcRef32 on 64-bit platforms
+            ofs = llmemory.remove_odd_value_marker(ofs)
+            item = obj + ofs
+            address = llop.show_from_adr32(llmemory.Address,
+                                           item.hiddengcref32[0])
+            if self.is_valid_gc_object(address):
+                newaddr = callback(address, arg)
+                if newaddr is not None:
+                    newaddr32 = llop.hide_into_adr32(llmemory.HiddenGcRef32,
+                                                     newaddr)
+                    item.hiddengcref32[0] = newaddr32
+        else:
+            # common case
+            item = obj + ofs
+            if self.points_to_valid_gc_object(item):
+                newaddr = callback(item.address[0], arg)
+                if newaddr is not None:
+                    item.address[0] = newaddr
+    _trace_see._annspecialcase_ = 'specialize:arg(3)'
+    _trace_see._always_inline_ = True
+
     def trace_partial(self, obj, start, stop, callback, arg):
         """Like trace(), but only walk the array part, for indices in
         range(start, stop).  Must only be called if has_gcptr_in_varsize().
@@ -218,7 +242,9 @@
             item += llmemory.gcarrayofptr_singleitemoffset * start
             while length > 0:
                 if self.points_to_valid_gc_object(item):
-                    callback(item, arg)
+                    newaddr = callback(item.address[0], arg)
+                    if newaddr is not None:
+                        item.address[0] = newaddr
                 item += llmemory.gcarrayofptr_singleitemoffset
                 length -= 1
             return
@@ -231,9 +257,7 @@
         while length > 0:
             j = 0
             while j < len(offsets):
-                itemobj = item + offsets[j]
-                if self.points_to_valid_gc_object(itemobj):
-                    callback(itemobj, arg)
+                self._trace_see(item, offsets[j], callback, arg)
                 j += 1
             item += itemlength
             length -= 1
@@ -279,8 +303,7 @@
         obj = root.address[0]
         ll_assert(bool(obj), "NULL address from walk_roots()")
         self._debug_record(obj)
-    def _debug_callback2(self, pointer, ignored):
-        obj = pointer.address[0]
+    def _debug_callback2(self, obj, ignored):
         ll_assert(bool(obj), "NULL address from self.trace()")
         self._debug_record(obj)
 

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/memory/gc/minimark.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/memory/gc/minimark.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/memory/gc/minimark.py	Mon Oct  4 15:30:22 2010
@@ -1025,19 +1025,17 @@
 
 
     def _trace_drag_out1(self, root):
-        self._trace_drag_out(root, None)
+        root.address[0] = self._trace_drag_out(root.address[0], None)
 
-    def _trace_drag_out(self, root, ignored):
-        obj = root.address[0]
+    def _trace_drag_out(self, obj, ignored):
         #
         # If 'obj' is not in the nursery, nothing to change.
         if not self.is_in_nursery(obj):
-            return
+            return obj
         #
         # If 'obj' was already forwarded, change it to its forwarding address.
         if self.is_forwarded(obj):
-            root.address[0] = self.get_forwarding_address(obj)
-            return
+            return self.get_forwarding_address(obj)
         #
         # First visit to 'obj': we must move it out of the nursery.
         size_gc_header = self.gcheaderbuilder.size_gc_header
@@ -1075,14 +1073,14 @@
         newobj = newhdr + size_gc_header
         llmemory.cast_adr_to_ptr(obj, FORWARDSTUBPTR).forw = newobj
         #
-        # Change the original pointer to this object.
-        root.address[0] = newobj
-        #
         # Add the newobj to the list 'old_objects_pointing_to_young',
         # because it can contain further pointers to other young objects.
         # We will fix such references to point to the copy of the young
         # objects when we walk 'old_objects_pointing_to_young'.
         self.old_objects_pointing_to_young.append(newobj)
+        #
+        # Change the original pointer to this newly built object.
+        return newobj
 
 
     def _malloc_out_of_nursery(self, totalsize):
@@ -1279,8 +1277,8 @@
     def _collect_ref(self, root):
         self.objects_to_trace.append(root.address[0])
 
-    def _collect_ref_rec(self, root, ignored):
-        self.objects_to_trace.append(root.address[0])
+    def _collect_ref_rec(self, obj, ignored):
+        self.objects_to_trace.append(obj)
 
     def visit_all_objects(self):
         pending = self.objects_to_trace
@@ -1421,8 +1419,8 @@
         self.objects_with_finalizers.delete()
         self.objects_with_finalizers = new_with_finalizer
 
-    def _append_if_nonnull(pointer, stack):
-        stack.append(pointer.address[0])
+    def _append_if_nonnull(obj, stack):
+        stack.append(obj)
     _append_if_nonnull = staticmethod(_append_if_nonnull)
 
     def _finalization_state(self, obj):

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/memory/gctypelayout.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/memory/gctypelayout.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/memory/gctypelayout.py	Mon Oct  4 15:30:22 2010
@@ -16,6 +16,8 @@
     """
     _alloc_flavor_ = 'raw'
 
+    # if config.translation.compressptr, the OFFSETS_TO_GC_PTR lists
+    # as odd integers the fields that are compressed pointers (UINT).
     OFFSETS_TO_GC_PTR = lltype.Array(lltype.Signed)
     ADDRESS_VOID_FUNC = lltype.FuncType([llmemory.Address], lltype.Void)
     FINALIZERTYPE = lltype.Ptr(ADDRESS_VOID_FUNC)
@@ -389,6 +391,8 @@
         #    (adr + off)
     elif isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc':
         offsets.append(0)
+    elif TYPE == llmemory.HiddenGcRef32:
+        offsets.append(llmemory.OddValueMarker())
     return offsets
 
 def gc_pointers_inside(v, adr, mutable_only=False):

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/memory/gcwrapper.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/memory/gcwrapper.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/memory/gcwrapper.py	Mon Oct  4 15:30:22 2010
@@ -88,7 +88,9 @@
     def setinterior(self, toplevelcontainer, inneraddr, INNERTYPE, newvalue,
                     offsets=()):
         if (lltype.typeOf(toplevelcontainer).TO._gckind == 'gc' and
-            isinstance(INNERTYPE, lltype.Ptr) and INNERTYPE.TO._gckind == 'gc'):
+            (isinstance(INNERTYPE, lltype.Ptr) and
+             INNERTYPE.TO._gckind == 'gc')
+            or INNERTYPE == llmemory.HiddenGcRef32):
             #
             wb = True
             if self.has_write_barrier_from_array:

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/memory/test/test_gc.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/memory/test/test_gc.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/memory/test/test_gc.py	Mon Oct  4 15:30:22 2010
@@ -77,6 +77,23 @@
         #assert simulator.current_size - curr < 16000 * INT_SIZE / 4
         #print "size before: %s, size after %s" % (curr, simulator.current_size)
 
+    def test_llinterp_instances(self):
+        class Cons(object):
+            def __init__(self, car, cdr):
+                self.car = car
+                self.cdr = cdr
+        def malloc_a_lot():
+            i = 0
+            while i < 10:
+                i += 1
+                a = Cons(1, Cons(2, Cons(i, None)))
+                b = a
+                j = 0
+                while j < 20:
+                    j += 1
+                    b = Cons(j, b)
+        res = self.interpret(malloc_a_lot, [])
+
     def test_global_list(self):
         lst = []
         def append_to_list(i, j):
@@ -776,3 +793,20 @@
 
 class TestMiniMarkGCCardMarking(TestMiniMarkGC):
     GC_PARAMS = {'card_page_indices': 4}
+
+class TestMiniMarkGCCompressPtr(TestMiniMarkGC):
+    def setup_class(cls):
+        TestMiniMarkGC.setup_class.im_func(cls)
+        #
+        from pypy.config.translationoption import IS_64_BITS
+        if not IS_64_BITS:
+            py.test.skip("only for 64-bits")
+        from pypy.config.pypyoption import get_pypy_config
+        cls._config = get_pypy_config(translating=True)
+        cls._config.translation.compressptr = True
+
+    def interpret(self, *args, **kwds):
+        if kwds.get('taggedpointers'):
+            py.test.skip("cannot have both taggedpointers and compressptr")
+        kwds['config'] = self._config
+        return super(TestMiniMarkGCCompressPtr, self).interpret(*args, **kwds)

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/memory/test/test_gctypelayout.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/memory/test/test_gctypelayout.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/memory/test/test_gctypelayout.py	Mon Oct  4 15:30:22 2010
@@ -37,6 +37,15 @@
     for T, c in [(GC_S, 0), (GC_S2, 2), (GC_A, 0), (GC_A2, 0), (GC_S3, 2)]:
         assert len(offsets_to_gc_pointers(T)) == c
 
+def test_hiddenptr32():
+    from pypy.rpython.lltypesystem.llmemory import HIDDENPTR32
+    from pypy.rpython.lltypesystem.llmemory import has_odd_value_marker
+    T = lltype.GcStruct('T', ('foo', lltype.Ptr(GC_S3)), ('bar', HIDDENPTR32))
+    ofs = offsets_to_gc_pointers(T)
+    assert len(ofs) == 2
+    assert not has_odd_value_marker(ofs[0])
+    assert has_odd_value_marker(ofs[1])
+
 def test_layout_builder(lltype2vtable=None):
     # XXX a very minimal test
     layoutbuilder = TypeLayoutBuilder(FakeGC, lltype2vtable)

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/raddress.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/raddress.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/raddress.py	Mon Oct  4 15:30:22 2010
@@ -2,7 +2,7 @@
 from pypy.tool.pairtype import pairtype
 from pypy.annotation import model as annmodel
 from pypy.rpython.lltypesystem.llmemory import NULL, Address, \
-     cast_adr_to_int, fakeaddress
+     cast_adr_to_int, fakeaddress, HiddenGcRef32, _hiddengcref32
 from pypy.rpython.rmodel import Repr, IntegerRepr
 from pypy.rpython.rptr import PtrRepr
 from pypy.rpython.lltypesystem import lltype
@@ -24,6 +24,13 @@
     def rtyper_makekey(self):
         return self.__class__, self.type
 
+class __extend__(annmodel.SomeHiddenGcRef32):
+    def rtyper_makerepr(self, rtyper):
+        return hiddengcref32_repr
+
+    def rtyper_makekey(self):
+        return self.__class__,
+
 class AddressRepr(Repr):
     lowleveltype = Address
 
@@ -139,4 +146,13 @@
     def convert_from_to((r_ptr, r_addr), v, llops):
         return llops.genop('cast_ptr_to_adr', [v], resulttype=Address)
 
+# ____________________________________________________________
+
+class HiddenGcRef32Repr(Repr):
+    lowleveltype = HiddenGcRef32
+
+    def convert_const(self, value):
+        assert isinstance(value, _hiddengcref32)
+        return value
 
+hiddengcref32_repr = HiddenGcRef32Repr()

Modified: pypy/branch/32ptr-on-64bit/pypy/rpython/rmodel.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/rpython/rmodel.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/rmodel.py	Mon Oct  4 15:30:22 2010
@@ -438,9 +438,21 @@
     from pypy.rpython import rclass
     if (isinstance(item_repr, rclass.AbstractInstanceRepr) and
         getattr(item_repr, 'gcflavor', 'gc') == 'gc'):
+        #if rtyper.annotator.translator.config.translation.compressptr:
+        #    return externalvsinternalfield(rtyper, item_repr)
         return item_repr, rclass.getinstancerepr(rtyper, None)
-    else:
-        return item_repr, item_repr
+    return item_repr, item_repr
+
+def externalvsinternalfield(rtyper, field_repr):
+    # usually a no-op, except if config.translation.compressptr, in which case
+    # it tries hard to return a wrapping compressed_gcref_repr
+    if rtyper.annotator.translator.config.translation.compressptr:
+        if (isinstance(field_repr.lowleveltype, Ptr) and
+            field_repr.lowleveltype.TO._gckind == 'gc'):
+            from pypy.rpython.lltypesystem import rcompressed
+            return (field_repr,
+                    rcompressed.get_compressed_gcref_repr(rtyper, field_repr))
+    return field_repr, field_repr
 
 
 class DummyValueBuilder(object):

Added: pypy/branch/32ptr-on-64bit/pypy/rpython/test/test_rcompressed.py
==============================================================================
--- (empty file)
+++ pypy/branch/32ptr-on-64bit/pypy/rpython/test/test_rcompressed.py	Mon Oct  4 15:30:22 2010
@@ -0,0 +1,28 @@
+import py
+from pypy.config.translationoption import IS_64_BITS
+from pypy.rpython.test import test_rclass
+
+
+def setup_module(mod):
+    if not IS_64_BITS:
+        py.test.skip("for 64-bits only")
+
+
+class MixinCompressed64(object):
+    def _get_config(self):
+        from pypy.config.pypyoption import get_pypy_config
+        config = get_pypy_config(translating=True)
+        config.translation.compressptr = True
+        return config
+
+    def interpret(self, *args, **kwds):
+        kwds['config'] = self._get_config()
+        return super(MixinCompressed64, self).interpret(*args, **kwds)
+
+    def interpret_raises(self, *args, **kwds):
+        kwds['config'] = self._get_config()
+        return super(MixinCompressed64, self).interpret_raises(*args, **kwds)
+
+
+class TestLLtype64(MixinCompressed64, test_rclass.TestLLtype):
+    pass

Modified: pypy/branch/32ptr-on-64bit/pypy/translator/c/database.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/translator/c/database.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/translator/c/database.py	Mon Oct  4 15:30:22 2010
@@ -55,6 +55,7 @@
         # assign to a constant object is something C doesn't think is
         # constant
         self.late_initializations = []
+        self.late_initializations_hiddengcref32 = []
         self.namespace = CNameManager()
 
         if translator is None or translator.rtyper is None:

Modified: pypy/branch/32ptr-on-64bit/pypy/translator/c/node.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/translator/c/node.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/translator/c/node.py	Mon Oct  4 15:30:22 2010
@@ -771,25 +771,33 @@
         yield '}'
 
 def generic_initializationexpr(db, value, access_expr, decoration):
-    if isinstance(typeOf(value), ContainerType):
+    TYPE = typeOf(value)
+    if isinstance(TYPE, ContainerType):
         node = db.getcontainernode(value)
         lines = list(node.initializationexpr(decoration+'.'))
         lines[-1] += ','
         return lines
     else:
         comma = ','
-        if typeOf(value) == Ptr(PyObject) and value:
+        if TYPE == Ptr(PyObject) and value:
             # cannot just write 'gxxx' as a constant in a structure :-(
             node = db.getcontainernode(value._obj)
             expr = 'NULL /*%s*/' % node.name
             node.where_to_copy_me.append('&%s' % access_expr)
-        elif typeOf(value) == Float and (isinf(value) or isnan(value)):
-            db.late_initializations.append(('%s' % access_expr, db.get(value)))
+        elif TYPE == Float and (isinf(value) or isnan(value)):
+            db.late_initializations.append((access_expr, db.get(value)))
             expr = '0.0 /* patched later by %sinfinity */' % (
                 '-+'[value > 0])
+        elif TYPE == llmemory.HiddenGcRef32:
+            if value.adr64:
+                db.late_initializations_hiddengcref32.append((access_expr,
+                                                              value))
+                expr = '0 /*HIDE_INTO_ADR32%s*/' % db.get(value.adr64.ptr)
+            else:
+                expr = '0'
         else:
             expr = db.get(value)
-            if typeOf(value) is Void:
+            if TYPE is Void:
                 comma = ''
         expr += comma
         i = expr.find('\n')

Modified: pypy/branch/32ptr-on-64bit/pypy/translator/c/primitive.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/translator/c/primitive.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/translator/c/primitive.py	Mon Oct  4 15:30:22 2010
@@ -7,7 +7,7 @@
 from pypy.rpython.lltypesystem.llmemory import Address, \
      AddressOffset, ItemOffset, ArrayItemsOffset, FieldOffset, \
      CompositeOffset, ArrayLengthOffset, \
-     GCHeaderOffset, GCREF, AddressAsInt
+     GCHeaderOffset, GCREF, AddressAsInt, HiddenGcRef32, OddValueMarker
 from pypy.rpython.lltypesystem.llarena import RoundedUpForAllocation
 from pypy.translator.c.support import cdecl, barebonearray
 
@@ -63,6 +63,8 @@
             return '(%s+%dL)' % (name, value.rest)
         elif isinstance(value, AddressAsInt):
             return '((long)%s)' % name_address(value.adr, db)
+        elif isinstance(value, OddValueMarker):
+            return '1 /*OddValueMarker*/'
         else:
             raise Exception("unimplemented symbolic %r"%value)
     if value is None:
@@ -145,6 +147,12 @@
     else:
         return 'NULL'
 
+def name_hiddengcref32(value, db):
+    # The only prebuilt HiddenGcRef32 that should occur in a translated C
+    # program occur as fields or items of a GcStruct or GcArray.
+    db.get(value.adr64)
+    return 'HIDE_INTO_ADR32(???) /* see primitive.py, name_hiddengcref32() */'
+
 def name_small_integer(value, db):
     """Works for integers of size at most INT or UINT."""
     if isinstance(value, Symbolic):
@@ -173,6 +181,7 @@
     Void:     name_void,
     Address:  name_address,
     GCREF:    name_gcref,
+    HiddenGcRef32: name_hiddengcref32,
     }
 
 PrimitiveType = {
@@ -188,6 +197,7 @@
     Void:     'void @',
     Address:  'void* @',
     GCREF:    'void* @',
+    HiddenGcRef32: 'hiddengcref32_t @',
     }
 
 def define_c_primitive(ll_type, c_name, suffix=''):

Modified: pypy/branch/32ptr-on-64bit/pypy/translator/c/src/commondefs.h
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/translator/c/src/commondefs.h	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/translator/c/src/commondefs.h	Mon Oct  4 15:30:22 2010
@@ -65,6 +65,15 @@
 #  define SIZEOF_LONG       8
 #  define SIZEOF_LONG_LONG  8
 
+   /* HiddenGcRef32 support (on 64-bits only) */
+   typedef unsigned int hiddengcref32_t;
+#  define uint32_t hiddengcref32_t
+#  define OP_SHOW_FROM_ADR32(x, r)  r = (void*)(((unsigned long)(x)) << 3)
+#  define OP_HIDE_INTO_ADR32(x, r)  \
+     r = (hiddengcref32_t)(((unsigned long)(x)) >> 3); \
+     RPyAssert((void*)(((unsigned long)(r)) << 3) == (x), \
+               "pointer too big or misaligned!")
+
 #endif
 
 /********************************************************/

Modified: pypy/branch/32ptr-on-64bit/pypy/translator/c/test/test_lladdresses.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/translator/c/test/test_lladdresses.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/translator/c/test/test_lladdresses.py	Mon Oct  4 15:30:22 2010
@@ -232,3 +232,43 @@
     assert res == 456
     res = fc(77)
     assert res == 123
+
+
+##class TestHiddenGcRef32(StandaloneTests):
+
+##    def setup_class(cls):
+##        from pypy.config.translationoption import IS_64_BITS
+##        if 0:# not IS_64_BITS:
+##            py.test.skip("only for 64-bits")
+
+##    def test_hiddengcref32(self):
+##        from pypy.rpython.lltypesystem.lloperation import llop
+##        S = lltype.GcStruct('S', ('x', lltype.Signed),
+##                                 ('y', HiddenGcRef32))
+##        prebuilt = lltype.malloc(S, immortal=True)
+##        prebuilt2 = lltype.malloc(S, immortal=True)
+##        prebuilt.x = 42
+##        prebuilt2.x = 53
+##        prebuilt.y = llop.hide_into_adr32(HiddenGcRef32, prebuilt2)
+##        prebuilt2.y = llop.hide_into_adr32(HiddenGcRef32, prebuilt)
+
+##        def check(a, b):
+##            p = llop.show_from_adr32(lltype.Ptr(S), a.y)
+##            assert p == b
+
+##        def f(argv):
+##            assert prebuilt.x == 42
+##            assert prebuilt2.x == 53
+##            check(prebuilt, prebuilt2)
+##            check(prebuilt2, prebuilt)
+##            p = lltype.malloc(S)
+##            p.y = llop.hide_into_adr32(HiddenGcRef32, prebuilt)
+##            prebuilt2.y = llop.hide_into_adr32(HiddenGcRef32, p)
+##            check(p, prebuilt)
+##            check(prebuilt2, p)
+##            check(prebuilt, prebuilt2)
+##            return 0
+
+##        fc = self.compile(f)
+##        res = fc([])
+##        assert res == 0

Modified: pypy/branch/32ptr-on-64bit/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/branch/32ptr-on-64bit/pypy/translator/c/test/test_newgc.py	(original)
+++ pypy/branch/32ptr-on-64bit/pypy/translator/c/test/test_newgc.py	Mon Oct  4 15:30:22 2010
@@ -18,6 +18,7 @@
     should_be_moving = False
     removetypeptr = False
     taggedpointers = False
+    compressptr = False
     GC_CAN_MOVE = False
     GC_CAN_MALLOC_NONMOVABLE = True
     GC_CAN_SHRINK_ARRAY = False
@@ -41,7 +42,8 @@
         t = Translation(main, standalone=True, gc=cls.gcpolicy,
                         policy=annpolicy.StrictAnnotatorPolicy(),
                         taggedpointers=cls.taggedpointers,
-                        gcremovetypeptr=cls.removetypeptr)
+                        gcremovetypeptr=cls.removetypeptr,
+                        compressptr=cls.compressptr)
         t.disable(['backendopt'])
         t.set_backend_extra_options(c_debug_defines=True)
         t.rtype()
@@ -623,7 +625,7 @@
         assert open(self.filename, 'r').read() == "hello world\n"
         os.unlink(self.filename)
 
-    def define_callback_with_collect(cls):
+    def XXXXXXXXXdefine_callback_with_collect(cls):
         from pypy.rlib.libffi import ffi_type_pointer, cast_type_to_ffitype,\
              CDLL, ffi_type_void, CallbackFuncPtr, ffi_type_sint
         from pypy.rpython.lltypesystem import rffi, ll2ctypes
@@ -1333,6 +1335,15 @@
     def test_gc_heap_stats(self):
         py.test.skip("not implemented")
 
+class TestMiniMarkGCCompressPtr(TestMiniMarkGC):
+    compressptr = True
+
+    def setup_class(cls):
+        from pypy.config.translationoption import IS_64_BITS
+        if not IS_64_BITS:
+            py.test.skip("only for 64-bits")
+        TestMiniMarkGC.setup_class.im_func(cls)
+
 # ____________________________________________________________________
 
 class TaggedPointersTest(object):



More information about the Pypy-commit mailing list